Merges node-osrm into repository

Build with

    cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On
This commit is contained in:
Daniel J. Hofmann 2017-03-01 18:27:57 +01:00 committed by Patrick Niklaus
parent ff238c2724
commit 2351b5a084
53 changed files with 4871 additions and 244 deletions

10
.gitignore vendored
View File

@ -46,7 +46,8 @@ Thumbs.db
#######################
/build/
/example/build/
/test/data/monaco*
/test/data/berlin*
/test/bindings/node/data/berlin*
/cmake/postinst
# Eclipse related files #
@ -86,7 +87,7 @@ stxxl.errlog
/test/cache
/test/speeds.csv
/test/penalties.csv
/test/data/monaco.*
/test/data/berlin.*
node_modules
# Deprecated config file #
@ -96,4 +97,7 @@ node_modules
*.swp
# local lua debugging file
debug.lua
debug.lua
# node-osrm artifacts
lib/binding

10
.npmignore Normal file
View File

@ -0,0 +1,10 @@
*
!README.md
!CHANGELOG.md
!CONTRIBUTING.MD
!LICENCE.TXT
!package.json
!example
!lib/*.js
!profiles/*
!profiles/lib/*

View File

@ -58,7 +58,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
# Release Builds
- os: linux
@ -67,7 +67,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
- os: linux
compiler: "gcc-6-release"
@ -81,7 +81,7 @@ matrix:
compiler: "gcc-6-release-i686"
env: >
TARGET_ARCH='i686' CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
CFLAGS='-m32 -msse2 -mfpmath=sse' CXXFLAGS='-m32 -msse2 -mfpmath=sse' CHECK_HEADERS=yes
CFLAGS='-m32 -msse2 -mfpmath=sse' CXXFLAGS='-m32 -msse2 -mfpmath=sse'
- os: linux
compiler: "gcc-4.9-release"
@ -142,7 +142,7 @@ before_install:
- echo "Using ${JOBS} jobs"
- source ./scripts/install_node.sh 4
- npm install -g "npm@>=3" # Upgrade to npm >v2 to reduce size of downloaded dependencies
- npm install
- npm install --ignore-scripts
# Bootstrap cmake to be able to run mason
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
- CMAKE_DIR="mason_packages/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}"
@ -173,7 +173,7 @@ install:
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_MASON=${ENABLE_MASON:-OFF} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS:-OFF} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} -DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} -DBUILD_TOOLS=ON -DENABLE_CCACHE=ON
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_MASON=${ENABLE_MASON:-OFF} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS:-OFF} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} -DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} -DBUILD_TOOLS=ON -DENABLE_CCACHE=ON -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF}
- echo "travis_fold:start:MAKE"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
@ -185,7 +185,6 @@ install:
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
sudo ldconfig
fi
- if [[ ${CHECK_HEADERS} == yes ]] ; then make check-headers ; fi
- popd
- mkdir example/build && pushd example/build
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
@ -196,7 +195,7 @@ install:
script:
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
- make -C test/data benchmark
- ./example/build/osrm-example test/data/monaco_CH.osrm
- ./example/build/osrm-example test/data/berlin_CH.osrm
# All tests assume to be run from the build directory
- pushd ${OSRM_BUILD_DIR}
- ./unit_tests/library-tests
@ -213,3 +212,11 @@ after_success:
if [ -n "${ENABLE_COVERAGE}" ]; then
bash <(curl -s https://codecov.io/bash)
fi
- |
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
nvm install 4
nvm use 4
source ./scripts/travis/build.sh
./scripts/travis/publish.sh
fi

View File

@ -1,5 +1,7 @@
# 5.7.0
- Changes from 5.6
- NodeJs Bindings
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
- Internals
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
- Files

View File

@ -24,6 +24,7 @@ option(ENABLE_SANITIZER "Use memory sanitizer for Debug build" OFF)
option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@ -800,6 +801,11 @@ add_custom_target(uninstall
add_subdirectory(unit_tests)
add_subdirectory(src/benchmarks)
if (ENABLE_NODE_BINDINGS)
add_subdirectory(src/nodejs)
endif()
if (ENABLE_FUZZING)
# Requires libosrm being built with sanitizers; make configurable and default to ubsan
set(FUZZ_SANITIZER "undefined" CACHE STRING "Sanitizer to be used for Fuzz testing")
@ -815,18 +821,21 @@ if (ENABLE_FUZZING)
endif ()
## add headers sanity check target that includes all headers independently
set(check_headers_dir "${PROJECT_BINARY_DIR}/check-headers")
file(GLOB_RECURSE headers_to_check
${PROJECT_BINARY_DIR}/*.hpp
${PROJECT_SOURCE_DIR}/include/*.hpp)
foreach(header ${headers_to_check})
get_filename_component(filename ${header} NAME_WE)
set(filename "${check_headers_dir}/${filename}.cpp")
if (NOT EXISTS ${filename})
file(WRITE ${filename} "#include \"${header}\"\n")
endif()
list(APPEND sources ${filename})
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
# add headers sanity check target that includes all headers independently
# make sure we have all deps for the nodejs sub project's includes (nan, node)
if (ENABLE_NODE_BINDINGS)
set(check_headers_dir "${PROJECT_BINARY_DIR}/check-headers")
file(GLOB_RECURSE headers_to_check
${PROJECT_BINARY_DIR}/*.hpp
${PROJECT_SOURCE_DIR}/include/*.hpp)
foreach(header ${headers_to_check})
get_filename_component(filename ${header} NAME_WE)
set(filename "${check_headers_dir}/${filename}.cpp")
if (NOT EXISTS ${filename})
file(WRITE ${filename} "#include \"${header}\"\n")
endif()
list(APPEND sources ${filename})
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
endif()

View File

@ -133,12 +133,12 @@ unit_tests\%Configuration%\server-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running library-tests.exe ...
SET test_region=monaco
SET test_region=berlin
SET test_osm=%test_region%.osm.pbf
SET test_osm_ch=%test_region%_CH.osm.pbf
SET test_osm_corech=%test_region%_CoreCH.osm.pbf
SET test_osm_mld=%test_region%_MLD.osm.pbf
IF NOT EXIST %test_osm% powershell Invoke-WebRequest https://s3.amazonaws.com/mapbox/osrm/testing/monaco.osm.pbf -OutFile %test_osm%
IF NOT EXIST %test_osm% powershell Invoke-WebRequest https://s3.amazonaws.com/mapbox/osrm/testing/berlin.osm.pbf -OutFile %test_osm%
COPY %test_osm% %test_osm_ch%
COPY %test_osm% %test_osm_corech%
COPY %test_osm% %test_osm_mld%

View File

@ -0,0 +1,587 @@
# Copyright (c) 2015, Colin Taylor
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# FindNodeJS.cmake CMake module vendored from the node-cmake project (v1.2).
# This script uses CMake 3.1+ features
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0)
message(FATAL_ERROR "FindNodeJS.cmake uses CMake 3.1+ features")
endif()
# Force a build type to be set (ignored on config based generators)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
endif()
# Capture module information
set(NodeJS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(NodeJS_MODULE_NAME ${NodeJS_MODULE_PATH} NAME)
# Allow users to specify the installed location of the Node.js package
set(NodeJS_ROOT_DIR "" CACHE PATH
"The root directory of the node.js installed package")
# Allow users to specify that downloaded sources should be used
option(NodeJS_DOWNLOAD "Download the required source files" Off)
# Allow users to force downloading of node packages
option(NodeJS_FORCE_DOWNLOAD "Download the source files every time" Off)
# Allow users to force archive extraction
option(NodeJS_FORCE_EXTRACT "Extract the archive every time" Off)
# Make libc++ the default when compiling with clang
option(NodeJS_USE_CLANG_STDLIB "Use libc++ when compiling with clang" On)
if(APPLE)
set(NodeJS_USE_CLANG_STDLIB On CACHE BOOL "" FORCE)
endif()
if(WIN32)
# Allow users to specify that the executable should be downloaded
option(NodeJS_DOWNLOAD_EXECUTABLE
"Download matching executable if available" Off
)
endif()
# Try to find the node.js executable
# The node executable under linux may not be the correct program
find_program(NodeJS_EXECUTABLE
NAMES node
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.platform"
OUTPUT_VARIABLE NodeJS_INSTALLED_PLATFORM
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.arch"
OUTPUT_VARIABLE NodeJS_INSTALLED_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
# If node isn't the node.js binary, try the nodejs binary
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
find_program(NodeJS_EXECUTABLE
NAMES nodejs
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
message(WARNING "Node.js executable could not be found. \
Set NodeJS_ROOT_DIR to the installed location of the executable or \
install Node.js to its default location.")
endif()
endif()
# Determine if a variant is set in the components
list(APPEND NodeJS_OTHER_COMPONENTS
X64 IA32 ARM WIN32 LINUX DARWIN
)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT False)
foreach(NodeJS_COMPONENT ${NodeJS_FIND_COMPONENTS})
list(FIND NodeJS_OTHER_COMPONENTS ${NodeJS_COMPONENT} NodeJS_OTHER_INDEX)
if(NodeJS_OTHER_INDEX EQUAL -1)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT True)
break()
endif()
endforeach()
# Get the targeted version of Node.js (or one of its derivatives)
if(NOT NodeJS_VERSION)
if(NodeJS_FIND_VERSION)
set(NodeJS_VERSION ${NodeJS_FIND_VERSION})
elseif(NodeJS_INSTALLED_VERSION AND NOT NodeJS_COMPONENTS_CONTAINS_VARIANT)
string(SUBSTRING ${NodeJS_INSTALLED_VERSION} 1 -1 NodeJS_VERSION)
else()
message(FATAL_ERROR "Node.js version is not set. Set the VERSION \
property of the find_package command to the required version of the \
Node.js sources")
endif()
endif()
# Determine the target platform for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. CMake architecture
#
set(NodeJS_PLATFORM "" CACHE STRING "Target node.js platform for module")
if(NOT NodeJS_PLATFORM)
if(NodeJS_EXECUTABLE)
set(NodeJS_PLATFORM ${NodeJS_INSTALLED_PLATFORM})
elseif(WIN32)
set(NodeJS_PLATFORM "win32")
elseif(UNIX)
if(APPLE)
set(NodeJS_PLATFORM "darwin")
else()
set(NodeJS_PLATFORM "linux")
endif()
else()
message(FATAL_ERROR "Node.js platform is not set. Add the platform \
to the find_package components section or set NodeJS_PLATFORM in the \
cache.")
endif()
endif()
# Convenience variables for the platform type
if(NodeJS_PLATFORM STREQUAL "win32")
set(NodeJS_PLATFORM_WIN32 True)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "linux")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX True)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "darwin")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN True)
endif()
# Determine the target architecture for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. Compiler architecture under MSVC
#
set(NodeJS_ARCH "" CACHE STRING "Target node.js architecture for module")
if(NOT NodeJS_ARCH)
if(NodeJS_EXECUTABLE)
set(NodeJS_ARCH ${NodeJS_INSTALLED_ARCH})
elseif(MSVC)
if(CMAKE_CL_64)
set(NodeJS_ARCH "x64")
else()
set(NodeJS_ARCH "ia32")
endif()
else()
message(FATAL_ERROR "Node.js architecture is not set. Add the \
architecture to the find_package components section or set NodeJS_ARCH \
in the cache.")
endif()
endif()
# Convenience variables for the architecture
if(NodeJS_ARCH STREQUAL "x64")
set(NodeJS_ARCH_X64 True)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "ia32")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 True)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "arm")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM True)
endif()
# Include helper functions
include(util/NodeJSUtil)
# Default variant name
# Used by the installed header comparison below
set(NodeJS_DEFAULT_VARIANT_NAME "node.js")
# Variables for Node.js artifacts across variants
# Specify all of these variables for each new variant
set(NodeJS_VARIANT_NAME "") # The printable name of the variant
set(NodeJS_VARIANT_BASE "") # A file name safe version of the variant
set(NodeJS_URL "") # The URL for the artifacts
set(NodeJS_SOURCE_PATH "") # The URL path of the source archive
set(NodeJS_CHECKSUM_PATH "") # The URL path of the checksum file
set(NodeJS_CHECKSUM_TYPE "") # The checksum type (algorithm)
set(NodeJS_WIN32_LIBRARY_PATH "") # The URL path of the windows library
set(NodeJS_WIN32_BINARY_PATH "") # The URL path of the windows executable
set(NodeJS_WIN32_LIBRARY_NAME "") # The name of the windows library
set(NodeJS_WIN32_BINARY_NAME "") # The name of the windows executable
set(NodeJS_DEFAULT_INCLUDE True) # Enable default include behavior
set(NodeJS_DEFAULT_LIBS True) # Include the default libraries
set(NodeJS_HAS_WIN32_PREFIX True) # Does the variant use library prefixes
set(NodeJS_HAS_WIN32_BINARY True) # Does the variant have win32 executables
set(NodeJS_HAS_OPENSSL True) # Does the variant include openssl headers
set(NodeJS_HEADER_VERSION 0.12.7) # Version after header-only archives start
set(NodeJS_SHA256_VERSION 0.7.0) # Version after sha256 checksums start
set(NodeJS_PREFIX_VERSION 0.12.7) # Version after windows prefixing starts
set(NodeJS_CXX11R_VERSION 0.12.7) # Version after c++11 is required
set(NodeJS_SOURCE_INCLUDE True) # Use the include paths from a source archive
set(NodeJS_HEADER_INCLUDE False) # Use the include paths from a header archive
set(NodeJS_INCLUDE_PATHS "") # Set of header dirs inside the source archive
set(NodeJS_LIBRARIES "") # The set of libraries to link with addon
set(NodeJS_WIN32_DELAYLOAD "") # Set of executables to delayload on windows
# NodeJS variants
# Selects download target based on configured component
# Include NodeJS last to provide default configurations when omitted
file(
GLOB NodeJS_SUPPORTED_VARIANTS
RELATIVE ${CMAKE_CURRENT_LIST_DIR}/variants
${CMAKE_CURRENT_LIST_DIR}/variants/*
)
foreach(NodeJS_SUPPORTED_VARIANT ${NodeJS_SUPPORTED_VARIANTS})
get_filename_component(NodeJS_SUPPORTED_VARIANT_NAME
${NodeJS_SUPPORTED_VARIANT} NAME_WE
)
if(NOT NodeJS_SUPPORTED_VARIANT_NAME STREQUAL "NodeJS")
include(variants/${NodeJS_SUPPORTED_VARIANT_NAME})
endif()
endforeach()
include(variants/NodeJS)
# Populate version variables, including version components
set(NodeJS_VERSION_STRING "v${NodeJS_VERSION}")
# Populate the remaining version variables
string(REPLACE "." ";" NodeJS_VERSION_PARTS ${NodeJS_VERSION})
list(GET NodeJS_VERSION_PARTS 0 NodeJS_VERSION_MAJOR)
list(GET NodeJS_VERSION_PARTS 1 NodeJS_VERSION_MINOR)
list(GET NodeJS_VERSION_PARTS 2 NodeJS_VERSION_PATCH)
# If the version we're looking for is the version that is installed,
# try finding the required headers. Don't do this under windows (where
# headers are not part of the installed content), when the user has
# specified that headers should be downloaded or when using a variant other
# than the default
if((NOT NodeJS_PLATFORM_WIN32) AND (NOT NodeJS_DOWNLOAD) AND
NodeJS_VARIANT_NAME STREQUAL NodeJS_DEFAULT_VARIANT_NAME AND
NodeJS_INSTALLED_VERSION STREQUAL NodeJS_VERSION_STRING AND
NodeJS_INSTALLED_PLATFORM STREQUAL NodeJS_PLATFORM AND
NodeJS_INSTALLED_ARCH STREQUAL NodeJS_ARCH)
# node.h is really generic and too easy for cmake to find the wrong
# file, so use the directory as a guard, and then just tack it on to
# the actual path
#
# Specifically ran into this under OSX, where python contains a node.h
# that gets found instead
find_path(NodeJS_INCLUDE_PARENT node/node.h)
set(NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_PARENT}/node)
# Under all systems that support this, there are no libraries required
# for linking (symbols are resolved via the main executable at runtime)
set(NodeJS_LIBRARIES "")
# Otherwise, headers and required libraries must be downloaded to the project
# to supplement what is installed
else()
# Create a folder for downloaded artifacts
set(NodeJS_DOWNLOAD_PATH
${CMAKE_CURRENT_BINARY_DIR}/${NodeJS_VARIANT_BASE}
)
set(NodeJS_DOWNLOAD_PATH ${NodeJS_DOWNLOAD_PATH}-${NodeJS_VERSION_STRING})
file(MAKE_DIRECTORY ${NodeJS_DOWNLOAD_PATH})
# Download the checksum file for validating all other downloads
# Conveniently, if this doesn't download correctly, the setup fails
# due to checksum failures
set(NodeJS_CHECKSUM_FILE ${NodeJS_DOWNLOAD_PATH}/CHECKSUM)
nodejs_download(
${NodeJS_URL}/${NodeJS_CHECKSUM_PATH}
${NodeJS_CHECKSUM_FILE}
${NodeJS_FORCE_DOWNLOAD}
)
file(READ ${NodeJS_CHECKSUM_FILE} NodeJS_CHECKSUM_DATA)
# Download and extract the main source archive
set(NodeJS_SOURCE_FILE ${NodeJS_DOWNLOAD_PATH}/headers.tar.gz)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_SOURCE_PATH} NodeJS_SOURCE_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_SOURCE_PATH}
${NodeJS_SOURCE_FILE}
${NodeJS_SOURCE_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
set(NodeJS_HEADER_PATH ${NodeJS_DOWNLOAD_PATH}/src)
nodejs_extract(
${NodeJS_SOURCE_FILE}
${NodeJS_HEADER_PATH}
${NodeJS_FORCE_EXTRACT}
)
# Populate include directories from the extracted source archive
foreach(NodeJS_HEADER_BASE ${NodeJS_INCLUDE_PATHS})
set(NodeJS_INCLUDE_DIR ${NodeJS_HEADER_PATH}/${NodeJS_HEADER_BASE})
if(NOT EXISTS ${NodeJS_INCLUDE_DIR})
message(FATAL_ERROR "Include does not exist: ${NodeJS_INCLUDE_DIR}")
endif()
list(APPEND NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_DIR})
endforeach()
# Download required library files when targeting windows
if(NodeJS_PLATFORM_WIN32)
# Download the windows library
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_WIN32_LIBRARY_FILE}/${NodeJS_WIN32_LIBRARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_LIBRARY_PATH}
NodeJS_WIN32_LIBRARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_LIBRARY_PATH}
${NodeJS_WIN32_LIBRARY_FILE}
${NodeJS_WIN32_LIBRARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
list(APPEND NodeJS_LIBRARIES ${NodeJS_WIN32_LIBRARY_FILE})
# If provided, download the windows executable
if(NodeJS_WIN32_BINARY_PATH AND
NodeJS_DOWNLOAD_EXECUTABLE)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_WIN32_BINARY_FILE}/${NodeJS_WIN32_BINARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_BINARY_PATH}
NodeJS_WIN32_BINARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_BINARY_PATH}
${NodeJS_WIN32_BINARY_FILE}
${NodeJS_WIN32_BINARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
endif()
endif()
endif()
# Support windows delay loading
if(NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LINK_FLAGS /IGNORE:4199)
set(NodeJS_WIN32_DELAYLOAD_CONDITION "")
foreach(NodeJS_WIN32_DELAYLOAD_BINARY ${NodeJS_WIN32_DELAYLOAD})
list(APPEND NodeJS_LINK_FLAGS
/DELAYLOAD:${NodeJS_WIN32_DELAYLOAD_BINARY}
)
list(APPEND NodeJS_WIN32_DELAYLOAD_CONDITION
"_stricmp(info->szDll, \"${NodeJS_WIN32_DELAYLOAD_BINARY}\") != 0"
)
endforeach()
string(REPLACE ";" " &&\n "
NodeJS_WIN32_DELAYLOAD_CONDITION
"${NodeJS_WIN32_DELAYLOAD_CONDITION}"
)
configure_file(
${NodeJS_MODULE_PATH}/src/win_delay_load_hook.c
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c @ONLY
)
list(APPEND NodeJS_ADDITIONAL_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c
)
endif()
# Allow undefined symbols on OSX
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_LINK_FLAGS "-undefined dynamic_lookup")
endif()
# Use libc++ when clang is the compiler by default
if(NodeJS_USE_CLANG_STDLIB AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*")
list(APPEND NodeJS_COMPILE_OPTIONS -stdlib=libc++)
endif()
# Require c++11 support after a specific point, but only if the user hasn't
# specified an override
if(NOT NodeJS_CXX_STANDARD)
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION)
set(NodeJS_CXX_STANDARD 11)
else()
set(NodeJS_CXX_STANDARD 98)
endif()
endif()
# Set required definitions
list(APPEND NodeJS_DEFINITIONS BUILDING_NODE_EXTENSION)
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
endif()
if(NOT NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_DEFINITIONS
_LARGEFILE_SOURCE
_FILE_OFFSET_BITS=64
)
endif()
function(add_nodejs_module NAME)
# Build a shared library for the module
add_library(${NAME} SHARED ${ARGN} ${NodeJS_ADDITIONAL_SOURCES})
# Include required headers
# Find and include Nan as well (always available as its a
# dependency of this module)
nodejs_find_module_fallback(nan ${CMAKE_CURRENT_SOURCE_DIR} NAN_PATH)
target_include_directories(${NAME}
PUBLIC ${NodeJS_INCLUDE_DIRS}
PUBLIC ${NAN_PATH}
)
# Set module properties
# This ensures proper naming of the module library across all platforms
get_target_property(COMPILE_OPTIONS ${NAME} COMPILE_OPTIONS)
if(NOT COMPILE_OPTIONS)
set(COMPILE_OPTIONS "")
endif()
set(COMPILE_OPTIONS ${COMPILE_OPTIONS} ${NodeJS_COMPILE_OPTIONS})
get_target_property(LINK_FLAGS ${NAME} LINK_FLAGS)
if(NOT LINK_FLAGS)
set(LINK_FLAGS "")
endif()
foreach(NodeJS_LINK_FLAG ${NodeJS_LINK_FLAGS})
set(LINK_FLAGS "${LINK_FLAGS} ${NodeJS_LINK_FLAG}")
endforeach()
set_target_properties(${NAME} PROPERTIES
PREFIX ""
SUFFIX ".node"
MACOSX_RPATH ON
POSITION_INDEPENDENT_CODE TRUE
COMPILE_OPTIONS "${COMPILE_OPTIONS}"
LINK_FLAGS "${LINK_FLAGS}"
CXX_STANDARD_REQUIRED TRUE
CXX_STANDARD ${NodeJS_CXX_STANDARD}
)
# Output the module in a per build type directory
# This makes builds consistent with visual studio and other generators
# that build by configuration
if(NOT CMAKE_CONFIGURATION_TYPES)
set_property(TARGET ${NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BUILD_TYPE}
)
endif()
# Set any required complier flags
# Mostly used under windows
target_compile_definitions(${NAME} PRIVATE ${NodeJS_DEFINITIONS})
# Link against required NodeJS libraries
target_link_libraries(${NAME} ${NodeJS_LIBRARIES})
endfunction()
# Write out the configuration for node scripts
configure_file(
${NodeJS_MODULE_PATH}/build.json.in
${CMAKE_CURRENT_BINARY_DIR}/build.json @ONLY
)
# Make sure we haven't violated the version-to-standard mapping
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION AND
NodeJS_CXX_STANDARD EQUAL 98)
message(FATAL_ERROR "${NodeJS_VARIANT_NAME} ${NodeJS_VERSION} \
requires C++11 or newer to build")
endif()
# This is a find_package file, handle the standard invocation
include(FindPackageHandleStandardArgs)
set(NodeJS_TARGET "${NodeJS_VARIANT_NAME} ${NodeJS_PLATFORM}/${NodeJS_ARCH}")
find_package_handle_standard_args(NodeJS
FOUND_VAR NodeJS_FOUND
REQUIRED_VARS NodeJS_TARGET NodeJS_INCLUDE_DIRS
VERSION_VAR NodeJS_VERSION
)
# Mark variables that users shouldn't modify
mark_as_advanced(
NodeJS_VALIDATE_EXECUTABLE
NodeJS_OTHER_COMPONENTS
NodeJS_COMPONENTS_CONTAINS_VARIANT
NodeJS_COMPONENT
NodeJS_OTHER_INDEX
NodeJS_VERSION_STRING
NodeJS_VERSION_MAJOR
NodeJS_VERSION_MINOR
NodeJS_VERSION_PATCH
NodeJS_VERSION_TWEAK
NodeJS_PLATFORM
NodeJS_PLATFORM_WIN32
NodeJS_PLATFORM_LINUX
NodeJS_PLATFORM_DARWIN
NodeJS_ARCH
NodeJS_ARCH_X64
NodeJS_ARCH_IA32
NodeJS_ARCH_ARM
NodeJS_DEFAULT_VARIANT_NAME
NodeJS_VARIANT_BASE
NodeJS_VARIANT_NAME
NodeJS_URL
NodeJS_SOURCE_PATH
NodeJS_CHECKSUM_PATH
NodeJS_CHECKSUM_TYPE
NodeJS_WIN32_LIBRARY_PATH
NodeJS_WIN32_BINARY_PATH
NodeJS_WIN32_LIBRARY_NAME
NodeJS_WIN32_BINARY_NAME
NodeJS_DEFAULT_INCLUDE
NodeJS_DEFAULT_LIBS
NodeJS_HAS_WIN32_BINARY
NodeJS_HEADER_VERSION
NodeJS_SHA256_VERISON
NodeJS_PREFIX_VERSION
NodeJS_SOURCE_INCLUDE
NodeJS_HEADER_INCLUDE
NodeJS_INCLUDE_PATHS
NodeJS_WIN32_DELAYLOAD
NodeJS_DOWNLOAD_PATH
NodeJS_CHECKSUM_FILE
NodeJS_CHECKSUM_DATA
NodeJS_SOURCE_FILE
NodeJS_SOURCE_CHECKSUM
NodeJS_HEADER_PATH
NodeJS_HEADER_BASE
NodeJS_INCLUDE_DIR
NodeJS_WIN32_LIBRARY_FILE
NodeJS_WIN32_LIBRARY_CHECKSUM
NodeJS_WIN32_BINARY_FILE
NodeJS_WIN32_BINARY_CHECKSUM
NodeJS_NAN_PATH
NodeJS_LINK_FLAGS
NodeJS_COMPILE_OPTIONS
NodeJS_ADDITIONAL_SOURCES
NodeJS_WIN32_DELAYLOAD_CONDITION
NodeJS_WIN32_DELAYLOAD_BINARY
NodeJS_TARGET
)

View File

@ -0,0 +1,10 @@
{
"build_type": "@CMAKE_BUILD_TYPE@",
"generator": "@CMAKE_GENERATOR@",
"toolset": "@CMAKE_GENERATOR_TOOLSET@",
"platform": "@CMAKE_GENERATOR_PLATFORM@",
"variant": "@NodeJS_VARIANT_BASE@",
"version": "@NodeJS_VERSION@",
"download": "@NodeJS_DOWNLOAD@",
"standard": "@NodeJS_CXX_STANDARD@"
}

View File

@ -0,0 +1,28 @@
set(GITHUB_API_TOKEN $ENV{GITHUB_API_TOKEN})
set(GITHUB_AUTH "")
if(GITHUB_API_TOKEN)
set(GITHUB_AUTH "?access_token=${GITHUB_API_TOKEN}")
endif()
set(GITHUB_API_URL "https://api.github.com")
function(github_get_rate_limit VAR)
set(RATE_LIMIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/GITHUBRATE)
set(RATE_LIMIT_URL ${GITHUB_API_URL}/rate_limit${GITHUB_AUTH})
nodejs_download(
${RATE_LIMIT_URL}
${RATE_LIMIT_FILE}
ON
)
file(READ ${RATE_LIMIT_FILE} RATE_LIMIT_DATA)
string(REGEX MATCH "\"remaining\": ([0-9]+),"
RATE_LIMIT_MATCH ${RATE_LIMIT_DATA})
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
mark_as_advanced(
GITHUB_AUTH
GITHUB_API_TOKEN
GITHUB_API_URL
)

View File

@ -0,0 +1,166 @@
function(nodejs_check_file FILE)
set(MESSAGE "File ${FILE} does not exist or is empty")
if(ARGC GREATER 1)
set(MESSAGE ${ARGV1})
endif()
# Make sure the file has contents
file(READ ${FILE} FILE_CONTENT LIMIT 1 HEX)
if(NOT FILE_CONTENT)
file(REMOVE ${FILE})
message(FATAL_ERROR ${MESSAGE})
endif()
endfunction()
function(nodejs_download URL FILE)
# Function optionally takes a checksum and a checksum type, and
# a force value
# Either can be specified without the other, but checksum must come first
if(ARGC GREATER 2)
set(CHECKSUM ${ARGV2})
if(CHECKSUM STREQUAL "On" OR CHECKSUM STREQUAL "ON" OR
CHECKSUM STREQUAL "True" OR CHECKSUM STREQUAL "TRUE" OR
CHECKSUM STREQUAL "Off" OR CHECKSUM STREQUAL "OFF" OR
CHECKSUM STREQUAL "False" OR CHECKSUM STREQUAL "FALSE")
set(FORCE ${CHECKSUM})
unset(CHECKSUM)
elseif(ARGC GREATER 3)
set(TYPE ${ARGV3})
else()
message(FATAL_ERROR "Checksum type must be specified")
endif()
elseif(ARGC GREATER 4)
set(CHECKSUM ${ARGV2})
set(TYPE ${ARGV3})
set(FORCE ${ARGV4})
endif()
# If the file exists, no need to download it again unless its being forced
if(NOT FORCE AND EXISTS ${FILE})
return()
endif()
# Download the file
message(STATUS "Downloading: ${URL}")
file(DOWNLOAD
${URL}
${FILE}
SHOW_PROGRESS
)
# Make sure the file has contents
nodejs_check_file(${FILE} "Unable to download ${URL}")
# If a checksum is provided, validate the downloaded file
if(CHECKSUM)
message(STATUS "Validating: ${FILE}")
file(${TYPE} ${FILE} DOWNLOAD_CHECKSUM)
message(STATUS "Checksum: ${CHECKSUM}")
message(STATUS "Download: ${DOWNLOAD_CHECKSUM}")
if(NOT CHECKSUM STREQUAL DOWNLOAD_CHECKSUM)
file(REMOVE ${FILE})
message(FATAL_ERROR "Validation failure: ${FILE}")
endif()
endif()
endfunction()
function(nodejs_checksum DATA FILE VAR)
string(REGEX MATCH "([A-Fa-f0-9]+)[\t ]+${FILE}" CHECKSUM_MATCH ${DATA})
if(CMAKE_MATCH_1)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
else()
message(FATAL_ERROR "Unable to extract file checksum")
endif()
endfunction()
function(nodejs_extract FILE DIR)
# Function optionally takes a force value
if(ARGC GREATER 2)
set(FORCE ${ARGV2})
endif()
# If the archvie has been extracted, no need to extract again unless it
# is being forced
if(NOT FORCE AND EXISTS ${DIR})
return()
endif()
# Make a temporary directory for extracting the output
set(EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/extract)
if(EXISTS ${EXTRACT_DIR})
file(REMOVE_RECURSE ${EXTRACT_DIR})
endif()
file(MAKE_DIRECTORY ${EXTRACT_DIR})
# Extract the archive
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xfz ${FILE}
WORKING_DIRECTORY ${EXTRACT_DIR}
)
# If only one element is extracted, the archive contained a nested
# folder; use the inner folder as the extracted folder
file(GLOB EXTRACT_CHILDREN ${EXTRACT_DIR}/*)
list(LENGTH EXTRACT_CHILDREN NUM_CHILDREN)
set(TARGET_DIR ${EXTRACT_DIR})
if(NUM_CHILDREN EQUAL 1)
list(GET EXTRACT_CHILDREN 0 TARGET_DIR)
endif()
# Move the folder to the target path
if(EXISTS ${DIR})
file(REMOVE_RECURSE ${DIR})
endif()
file(RENAME ${TARGET_DIR} ${DIR})
# Make sure to clean up the extraction folder when the inner folder
# is used
file(REMOVE_RECURSE ${EXTRACT_DIR})
endfunction()
function(nodejs_find_module NAME BASE PATH)
# Find a node module using the same search path that require uses
# without needing a node binary
set(ROOT ${BASE})
set(DRIVE "^[A-Za-z]?:?/$")
# Walk up the directory tree until at the root
while(NOT ROOT MATCHES ${DRIVE} AND NOT
EXISTS ${ROOT}/node_modules/${NAME})
get_filename_component(ROOT ${ROOT} DIRECTORY)
endwhile()
# Operate like the CMake find_* functions, returning NOTFOUND if the
# module can't be found
if(ROOT MATCHES ${DRIVE})
set(${PATH} ${NAME}-NOTFOUND PARENT_SCOPE)
else()
set(${PATH} ${ROOT}/node_modules/${NAME} PARENT_SCOPE)
endif()
endfunction()
macro(nodejs_find_module_fallback NAME BASE PATH)
# Look in the provided path first
# If the module isn't found, try searching from the module
nodejs_find_module(${NAME} ${BASE} ${PATH})
if(NOT ${PATH})
nodejs_find_module(${NAME} ${NodeJS_MODULE_PATH} ${PATH})
endif()
endmacro()
function(nodejs_get_version URL VAR)
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/VERSION)
nodejs_download(
${URL}
${VERSION_FILE}
ON
)
nodejs_check_file(${VERSION_FILE})
file(READ ${VERSION_FILE} VERSION_DATA)
string(REGEX MATCH "v([0-9]+\.[0-9]+\.[0-9]+)"
VERSION_MATCH ${VERSION_DATA}
)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,81 @@
set(ELECTRON_VARIANT_BASE "electron")
set(ELECTRON_WIN32_BINARY_NAME "${ELECTRON_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${ELECTRON_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_ELECTRON OR
NodeJS_VARIANT STREQUAL ${ELECTRON_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
include(util/Github)
github_get_rate_limit(GITHUB_RATE_LIMIT)
# Handle determining the latest release
# Very complicated, due to electron not following the "latest"
# convention of other variants
set(ELECTRON_LATEST_RELEASE_FILE ${CMAKE_CURRENT_BINARY_DIR}/ELECTRON)
set(ELECTRON_LATEST_RELEASE_URL
${GITHUB_API_URL}/repos/atom/electron/releases/latest${GITHUB_AUTH}
)
if(GITHUB_RATE_LIMIT GREATER 0)
nodejs_download(
${ELECTRON_LATEST_RELEASE_URL}
${ELECTRON_LATEST_RELEASE_FILE}
ON
)
endif()
nodejs_check_file(
${ELECTRON_LATEST_RELEASE_FILE}
"Releases file could not be downloaded, likely \
because github rate limit was exceeded. Wait until the limit \
passes or set GITHUB_API_TOKEN in your environment to a valid \
github developer token."
)
file(READ ${ELECTRON_LATEST_RELEASE_FILE} ELECTRON_LATEST_RELEASE_DATA)
string(REGEX MATCH "\"tag_name\"\: \"v([0-9]+\.[0-9]+\.[0-9]+)\""
ELECTRON_LATEST_RELEASE_MATCH ${ELECTRON_LATEST_RELEASE_DATA})
set(NodeJS_VERSION ${CMAKE_MATCH_1})
endif()
set(NodeJS_VARIANT_NAME "Electron.js")
# SHASUMS of any kind is inaccessible prior to 0.16.0
if(NodeJS_VERSION VERSION_LESS 0.16.0)
message(FATAL_ERROR "Electron is only supported for versions >= 0.16.0")
endif()
# Electron switched to IOJS after 0.25.0
# Probably needs to be bounded on the upper side if/when they switch
# back to node mainline due to iojs-node merge
set(NodeJS_VARIANT_BASE "node")
if(NodeJS_VERSION VERSION_GREATER 0.25.0)
set(NodeJS_VARIANT_BASE "iojs")
endif()
# Url is hard to get, because it will immediately resolve to a CDN
# Extracted from the electron website
set(NodeJS_URL
"https://atom.io/download/atom-shell/v${NodeJS_VERSION}"
)
# Headers become available for IOJS base ONLY!
# Variant base switch above handles this
set(NodeJS_HEADER_VERSION 0.30.1)
# Header only archive uses source style paths
set(NodeJS_DEFAULT_INCLUDE False)
# Hard to determine, but versions seem to start at 16, and SHA256 is
# available
set(NodeJS_SHA256_VERSION 0.15.9)
# C++11 and Prefixing start after the IOJS switch
# Will carry forward after node mainline so no need for upper bound (whew)
set(NodeJS_PREFIX_VERSION 0.25.0)
set(NodeJS_CXX11R_VERSION 0.25.0)
# The executable is not provided on the CDN
# In theory, I could support a BINARY_URL to get this from github
set(NodeJS_HAS_WIN32_BINARY False)
# OpenSSL isn't included in the headers
set(NodeJS_HAS_OPENSSL False)
endif()

View File

@ -0,0 +1,25 @@
set(IOJS_URL_BASE "https://iojs.org/dist")
set(IOJS_VARIANT_BASE "iojs")
set(IOJS_WIN32_BINARY_NAME "${IOJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${IOJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_IOJS OR NodeJS_VARIANT STREQUAL ${IOJS_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
set(IOJS_LATEST_RELEASE_URL
"${IOJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${IOJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "io.js")
set(NodeJS_VARIANT_BASE ${IOJS_VARIANT_BASE})
set(NodeJS_URL "${IOJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_HEADER_VERSION 2.3.1)
set(NodeJS_WIN32_BINARY_NAME "${IOJS_WIN32_BINARY_NAME}")
endif()
mark_as_advanced(
IOJS_URL_BASE
IOJS_VARIANT_BASE
IOJS_WIN32_BINARY_NAME
IOJS_LATEST_RELEASE_URL
)

View File

@ -0,0 +1,30 @@
set(NWJS_URL_BASE "http://dl.nwjs.io")
set(NWJS_VARIANT_BASE "nw")
set(NWJS_WIN32_BINARY_NAME "${NWJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NWJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_NWJS OR NodeJS_VARIANT STREQUAL ${NWJS_VARIANT_BASE})
set(NodeJS_CHECKSUM_PATH "MD5SUMS")
set(NodeJS_CHECKSUM_TYPE "MD5")
if(NodeJS_VERSION STREQUAL "latest")
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
nodejs_get_version(${NWJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "nw.js")
set(NodeJS_VARIANT_BASE ${NWJS_VARIANT_BASE})
set(NodeJS_URL "${NWJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_SOURCE_PATH "nw-headers-v${NodeJS_VERSION}.tar.gz")
set(NodeJS_DEFAULT_INCLUDE False)
set(NodeJS_HAS_WIN32_PREFIX False)
set(NodeJS_HAS_WIN32_BINARY False)
endif()
mark_as_advanced(
NWJS_URL_BASE
NWJS_VARIANT_BASE
NWJS_WIN32_BINARY_NAME
NWJS_LATEST_RELEASE_URL
)

View File

@ -0,0 +1,131 @@
set(NodeJS_URL_BASE http://nodejs.org/dist)
set(NodeJS_DEFAULT_VARIANT_BASE "node")
set(NodeJS_DEFAULT_WIN32_BINARY_NAME "${NodeJS_DEFAULT_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NodeJS_DEFAULT_WIN32_BINARY_NAME})
if(NodeJS_VERSION STREQUAL "latest")
set(NodeJS_LATEST_RELEASE_URL
"${NodeJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${NodeJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
if(NOT NodeJS_VARIANT_NAME)
set(NodeJS_VARIANT_NAME ${NodeJS_DEFAULT_VARIANT_NAME})
endif()
if(NOT NodeJS_VARIANT_BASE)
set(NodeJS_VARIANT_BASE ${NodeJS_DEFAULT_VARIANT_BASE})
endif()
if(NOT NodeJS_URL)
set(NodeJS_URL "${NodeJS_URL_BASE}/v${NodeJS_VERSION}")
endif()
if(NOT NodeJS_SOURCE_PATH)
set(NodeJS_SOURCE_PATH "${NodeJS_VARIANT_BASE}-v${NodeJS_VERSION}")
# Use the headers archive when its available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}-headers")
endif()
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}.tar.gz")
endif()
if(NodeJS_DEFAULT_INCLUDE AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_INCLUDE False)
set(NodeJS_HEADER_INCLUDE True)
endif()
if(NodeJS_SOURCE_INCLUDE)
list(APPEND NodeJS_INCLUDE_PATHS
src
deps/uv/include
deps/v8/include
deps/zlib
)
# OpenSSL is an optional header
if(NodeJS_HAS_OPENSSL)
list(APPEND NodeJS_INCLUDE_PATHS
deps/openssl/openssl/include
)
endif()
endif()
if(NodeJS_HEADER_INCLUDE)
set(NodeJS_INCLUDE_PATHS include/node)
endif()
if(NOT NodeJS_CHECKSUM_TYPE)
# Use SHA256 when available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_SHA256_VERSION})
set(NodeJS_CHECKSUM_TYPE "SHA256")
else()
set(NodeJS_CHECKSUM_TYPE "SHA1")
endif()
endif()
if(NOT NodeJS_CHECKSUM_PATH)
set(NodeJS_CHECKSUM_PATH "SHASUMS")
if(NodeJS_CHECKSUM_TYPE STREQUAL "SHA256")
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}256")
endif()
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}.txt")
endif()
# Library and binary are based on variant base
if(NOT NodeJS_WIN32_LIBRARY_NAME)
set(NodeJS_WIN32_LIBRARY_NAME ${NodeJS_VARIANT_BASE}.lib)
endif()
if(NOT NodeJS_WIN32_BINARY_NAME)
set(NodeJS_WIN32_BINARY_NAME ${NodeJS_VARIANT_BASE}.exe)
endif()
if(NOT NodeJS_WIN32_LIBRARY_PATH)
# The library location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_LIBRARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x64/")
endif()
set(NodeJS_WIN32_LIBRARY_PATH
"${NodeJS_WIN32_LIBRARY_PATH}${NodeJS_WIN32_LIBRARY_NAME}"
)
endif()
if(NodeJS_HAS_WIN32_BINARY AND NOT NodeJS_WIN32_BINARY_PATH)
# The executable location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_BINARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x64/")
endif()
set(NodeJS_WIN32_BINARY_PATH
"${NodeJS_WIN32_BINARY_PATH}${NodeJS_WIN32_BINARY_NAME}"
)
endif()
# Specify windows libraries
# XXX: This may need to be version/variant specific in the future
if(NodeJS_DEFAULT_LIBS AND NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LIBRARIES
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
odbc32.lib DelayImp.lib
)
endif()
mark_as_advanced(
NodeJS_URL_BASE
NodeJS_DEFAULT_VARIANT_BASE
NodeJS_DEFAULT_WIN32_BINARY_NAME
NodeJS_LATEST_RELEASE_URL
)

333
docs/bindings/node/api.md Normal file
View File

@ -0,0 +1,333 @@
# OSRM
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
which is prepared by the OSRM Backend C++ library.
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
node_modules/osrm/lib/binding/osrm-contract data.osrm
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
methods below. To create an OSRM instance with your network you need to construct an instance like this:
```javascript
var osrm = new OSRM('network.osrm');
```
#### Methods
| Service | Description |
| -------------------------- | --------------------------------------------------------- |
| [`osrm.route`](#route) | shortest path between given coordinates |
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
| [`osrm.table`](#table) | computes distance tables for given coordinates |
| [`osrm.match`](#match) | matches given coordinates to the road network |
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
#### General Options
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
| Option | Values | Description | Format |
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
## route
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
- `options.alternatives` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Search for alternative routes and return as well. _Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. `null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
if(err) throw err;
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
});
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
## nearest
Snaps a coordinate to the street network and returns the nearest n matches.
Note: `coordinates` in the general options only supports a single `{longitude},{latitude}` entry.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [[13.388860,52.517037]],
number: 3,
bearings: [[0,20]]
};
osrm.nearest(options, function(err, response) {
console.log(response.waypoints); // array of Waypoint objects
});
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied
input coordinate.
## table
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
location with given index as source. Default is to use all.
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.388860,52.517037],
[13.397634,52.529407],
[13.428555,52.523219]
]
};
osrm.table(options, function(err, response) {
console.log(response.durations); // array of arrays, matrix in row-major order
console.log(response.sources); // array of Waypoint objects
console.log(response.destinations); // array of Waypoint objects
});
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
## tile
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
so are in sync with actual routing results, and let you examine which roads are actually routable,
and what weights they have applied.
**Parameters**
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS]\(<https://www.mapbox.com/mapbox-gl-js/api/>.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
osrm.tile([0, 0, 0], function(err, response) {
if (err) throw err;
fs.writeFileSync('./tile.vector.pbf', response); // write the buffer to a file
});
```
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
## match
Map matching matches given GPS points to the road network in the most plausible way.
Please note the request might result multiple sub-traces. Large jumps in the timestamps
(>60s) or improbable transitions lead to trace splits if a complete matching could
not be found. The algorithm might not be able to match all points. Outliers are removed
if they can not be matched successfully.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified`
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
If applicable use GPS accuracy (`double >= 0`, default `5m`).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: [1424684612, 1424684616, 1424684620]
};
osrm.match(options, function(err, response) {
if (err) throw err;
console.log(response.tracepoints); // array of Waypoint objects
console.log(response.matchings); // array of Route objects
});
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
If the trace point was ommited by map matching because it is an outlier, the entry will be null. Each
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
## trip
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm). The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation. Note that all input coordinates have to be connected for the trip service to work.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.roundtrip` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route is a roundtrip. (optional, default `true`)
- `options.source` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route starts at `any` coordinate. Can also be `first`. (optional, default `any`)
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Fixing Start and End Points**
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible:
| roundtrip | source | destination | supported |
| :-- | :-- | :-- | :-- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
| true | any | any | **yes** |
| false | first | last | **yes** |
| false | first | any | no |
| false | any | last | no |
| false | any | any | no |
**Examples**
Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
}
osrm.trip(options, function(err, response) {
if (err) throw err;
console.log(response.waypoints); // array of Waypoint objects
console.log(response.trips); // array of Route objects
});
```
Non Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
],
source: "first",
destination: "last",
roundtrip: false
}
osrm.trip(options, function(err, response) {
if (err) throw err;
console.log(response.waypoints); // array of Waypoint objects
console.log(response.trips); // array of Route objects
});
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
# Responses
Responses
## Route
Represents a route through (potentially multiple) waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
## RouteLeg
Represents a route between two waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
## RouteStep
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a single way to the subsequent step.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
## StepManeuver
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
## Waypoint
Object used to describe waypoint on a route.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)

View File

@ -0,0 +1,86 @@
# Releasing
Releasing a new version of `node-osrm` is mostly automated using Travis CI.
The version of `node-osrm` is locked to the same version as `osrm-backend`. Every `node-osrm` should have a `osrm-backend` release of the same version. Of course, only release a `node-osrm` after the release has been tagged in `osrm-backend`.
These steps all happen on `master`. After the release is out, create a branch using the MAJOR.MINOR version of the release to document code changes made for that version.
### Steps to release
1. Update the `osrm_release` field in `package.json` to the corresonding git tag in `osrm-backend.`
Confirm the desired OSRM branch and commit to `master`.
1. Bump node-osrm version
Update the `CHANGELOG.md` and the `package.json` version if needed.
1. Check that Travis CI [builds are passing](https://travis-ci.org/Project-OSRM/node-osrm) for the latest commit on `master`.
1. Publishing binaries
If travis builds are passing then it's time to publish binaries by committing with a message containing `[publish binary]`. Use an empty commit for this.
```
git commit --allow-empty -m "[publish binary] vMAJOR.MINOR.PATCH"
```
1. Test
Locally you can now test binaries. Cleanup, re-install, and run the tests like:
```
make clean
npm install # will pull remote binaries
npm ls # confirm deps are correct
make test
```
1. Tag
Once binaries are published for Linux and OS X then its time to tag a new release and add the changelog to the tag:
```
git tag vMAJOR.MINOR.PATCH -a
git push --tags
```
1. Publish node-osrm. **we only do this for stable releases**
First ensure your local `node-pre-gyp` is up to date:
```
npm ls
```
This is important because it is bundled during packaging.
If you see any errors then do:
```
rm -rf node_modules/node-pre-gyp
npm install node-pre-gyp
```
Now we're ready to publish `node-osrm` to <https://www.npmjs.org/package/osrm>:
```
npm publish
```
Dependent apps can now pull from the npm registry like:
```
"dependencies": {
"osrm": "^MAJOR.MINOR.PATCH"
}
```
Or can still pull from the github tag like:
```
"dependencies": {
"osrm": "https://github.com/Project-OSRM/node-osrm/archive/vMAJOR.MINOR.PATCH.tar.gz"
}
```

View File

@ -46,12 +46,6 @@ You should see the compiled binaries in `build/unit_tests`, you can then run eac
./engine-tests
```
For `library-tests` you will need to provide a path to the test data:
```
./library-tests ../../test/data/monaco.osrm
```
## Cucumber
For a general introduction on cucumber in our testsuite, have a look at [the wiki](https://github.com/Project-OSRM/osrm-backend/wiki/Cucumber-Test-Suite).

View File

@ -39,9 +39,9 @@ int main(int argc, const char *argv[])
// The following shows how to use the Route service; configure this service
RouteParameters params;
// Route in monaco
params.coordinates.push_back({util::FloatLongitude{7.419758}, util::FloatLatitude{43.731142}});
params.coordinates.push_back({util::FloatLongitude{7.419505}, util::FloatLatitude{43.736825}});
// Route in Berlin: Alexanderplatz to Hackescher Markt
params.coordinates.push_back({util::FloatLongitude{13.414307}, util::FloatLatitude{52.521835}});
params.coordinates.push_back({util::FloatLongitude{13.402290}, util::FloatLatitude{52.523728}});
// Response is in JSON format
json::Object result;
@ -59,7 +59,7 @@ int main(int argc, const char *argv[])
const auto duration = route.values["duration"].get<json::Number>().value;
// Warn users if extract does not contain the default Berlin coordinates from above
if (distance == 0 or duration == 0)
if (distance == 0 || duration == 0)
{
std::cout << "Note: distance or duration is zero. ";
std::cout << "You are probably doing a query outside of the OSM extract.\n\n";

32
example/example.js Normal file
View File

@ -0,0 +1,32 @@
process.env.UV_THREADPOOL_SIZE = Math.ceil(require('os').cpus().length * 1.5);
var express = require('express');
var OSRM = require('..');
var path = require('path');
var app = express();
var osrm = new OSRM(path.join(__dirname,"../test/data/berlin_CH.osrm"));
// Accepts a query like:
// http://localhost:8888?start=13.414307,52.521835&end=13.402290,52.523728
app.get('/', function(req, res) {
if (!req.query.start || !req.query.end) {
return res.json({"error":"invalid start and end query"});
}
var coordinates = [];
var start = req.query.start.split(',');
coordinates.push([+start[0],+start[1]]);
var end = req.query.end.split(',');
coordinates.push([+end[0],+end[1]]);
var query = {
coordinates: coordinates,
alternateRoute: req.query.alternatives !== 'false'
};
osrm.route(query, function(err, result) {
if (err) return res.json({"error":err.message});
return res.json(result);
});
});
console.log('Listening on port: ' + 8888);
app.listen(8888);

View File

@ -0,0 +1,65 @@
#ifndef OSRM_BINDINGS_NODE_JSON_V8_RENDERER_HPP
#define OSRM_BINDINGS_NODE_JSON_V8_RENDERER_HPP
#include "osrm/json_container.hpp"
#include <nan.h>
#include <functional>
namespace node_osrm
{
struct V8Renderer
{
explicit V8Renderer(v8::Local<v8::Value> &_out) : out(_out) {}
void operator()(const osrm::json::String &string) const
{
out = Nan::New(std::cref(string.value)).ToLocalChecked();
}
void operator()(const osrm::json::Number &number) const { out = Nan::New(number.value); }
void operator()(const osrm::json::Object &object) const
{
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
for (const auto &keyValue : object.values)
{
v8::Local<v8::Value> child;
mapbox::util::apply_visitor(V8Renderer(child), keyValue.second);
obj->Set(Nan::New(keyValue.first).ToLocalChecked(), child);
}
out = obj;
}
void operator()(const osrm::json::Array &array) const
{
v8::Local<v8::Array> a = Nan::New<v8::Array>(array.values.size());
for (auto i = 0u; i < array.values.size(); ++i)
{
v8::Local<v8::Value> child;
mapbox::util::apply_visitor(V8Renderer(child), array.values[i]);
a->Set(i, child);
}
out = a;
}
void operator()(const osrm::json::True &) const { out = Nan::New(true); }
void operator()(const osrm::json::False &) const { out = Nan::New(false); }
void operator()(const osrm::json::Null &) const { out = Nan::Null(); }
private:
v8::Local<v8::Value> &out;
};
inline void renderToV8(v8::Local<v8::Value> &out, const osrm::json::Object &object)
{
osrm::json::Value value = object;
mapbox::util::apply_visitor(V8Renderer(out), value);
}
}
#endif // JSON_V8_RENDERER_HPP

View File

@ -0,0 +1,41 @@
#ifndef OSRM_BINDINGS_NODE_HPP
#define OSRM_BINDINGS_NODE_HPP
#include "osrm/osrm_fwd.hpp"
#include <nan.h>
#include <memory>
namespace node_osrm
{
struct Engine final : public Nan::ObjectWrap
{
using Base = Nan::ObjectWrap;
static NAN_MODULE_INIT(Init);
static NAN_METHOD(New);
static NAN_METHOD(route);
static NAN_METHOD(nearest);
static NAN_METHOD(table);
static NAN_METHOD(tile);
static NAN_METHOD(match);
static NAN_METHOD(trip);
Engine(osrm::EngineConfig &config);
// Thread-safe singleton accessor
static Nan::Persistent<v8::Function> &constructor();
// Ref-counted OSRM alive even after shutdown until last callback is done
std::shared_ptr<osrm::OSRM> this_;
};
} // ns node_osrm
NODE_MODULE(osrm, node_osrm::Engine::Init)
#endif

View File

@ -0,0 +1,922 @@
#ifndef OSRM_BINDINGS_NODE_SUPPORT_HPP
#define OSRM_BINDINGS_NODE_SUPPORT_HPP
#include "nodejs/json_v8_renderer.hpp"
#include "osrm/bearing.hpp"
#include "osrm/coordinate.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/json_container.hpp"
#include "osrm/match_parameters.hpp"
#include "osrm/nearest_parameters.hpp"
#include "osrm/osrm.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/status.hpp"
#include "osrm/storage_config.hpp"
#include "osrm/table_parameters.hpp"
#include "osrm/tile_parameters.hpp"
#include "osrm/trip_parameters.hpp"
#include <boost/assert.hpp>
#include <boost/make_unique.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <exception>
#include <memory>
#include <utility>
namespace node_osrm
{
using engine_config_ptr = std::unique_ptr<osrm::EngineConfig>;
using route_parameters_ptr = std::unique_ptr<osrm::RouteParameters>;
using trip_parameters_ptr = std::unique_ptr<osrm::TripParameters>;
using tile_parameters_ptr = std::unique_ptr<osrm::TileParameters>;
using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
template <> v8::Local<v8::Value> inline render(const std::string &result)
{
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
}
template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
{
v8::Local<v8::Value> value;
renderToV8(value, result);
return value;
}
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
{
const auto code_iter = result.values.find("code");
const auto end_iter = result.values.end();
BOOST_ASSERT(code_iter != end_iter);
if (result_status == osrm::Status::Error)
{
throw std::logic_error(code_iter->second.get<osrm::json::String>().value.c_str());
}
result.values.erase(code_iter);
const auto message_iter = result.values.find("message");
if (message_iter != end_iter)
{
result.values.erase(message_iter);
}
}
inline void ParseResult(const osrm::Status &result_status, const std::string & /*unused*/) {}
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
Nan::HandleScope scope;
auto engine_config = boost::make_unique<osrm::EngineConfig>();
if (args.Length() == 0)
{
return engine_config;
}
else if (args.Length() > 1)
{
Nan::ThrowError("Only accepts one parameter");
return engine_config_ptr();
}
BOOST_ASSERT(args.Length() == 1);
if (args[0]->IsString())
{
engine_config->storage_config = osrm::StorageConfig(
*v8::String::Utf8Value(Nan::To<v8::String>(args[0]).ToLocalChecked()));
engine_config->use_shared_memory = false;
return engine_config;
}
else if (!args[0]->IsObject())
{
Nan::ThrowError("Parameter must be a path or options object");
return engine_config_ptr();
}
BOOST_ASSERT(args[0]->IsObject());
auto params = Nan::To<v8::Object>(args[0]).ToLocalChecked();
auto path = params->Get(Nan::New("path").ToLocalChecked());
auto shared_memory = params->Get(Nan::New("shared_memory").ToLocalChecked());
if (!path->IsUndefined())
{
engine_config->storage_config =
osrm::StorageConfig(*v8::String::Utf8Value(Nan::To<v8::String>(path).ToLocalChecked()));
}
if (!shared_memory->IsUndefined())
{
if (shared_memory->IsBoolean())
{
engine_config->use_shared_memory = Nan::To<bool>(shared_memory).FromJust();
}
else
{
Nan::ThrowError("Shared_memory option must be a boolean");
return engine_config_ptr();
}
}
if (path->IsUndefined() && !engine_config->use_shared_memory)
{
Nan::ThrowError("Shared_memory must be enabled if no path is "
"specified");
return engine_config_ptr();
}
return engine_config;
}
inline boost::optional<std::vector<osrm::Coordinate>>
parseCoordinateArray(const v8::Local<v8::Array> &coordinates_array)
{
Nan::HandleScope scope;
boost::optional<std::vector<osrm::Coordinate>> resulting_coordinates;
std::vector<osrm::Coordinate> temp_coordinates;
for (uint32_t i = 0; i < coordinates_array->Length(); ++i)
{
v8::Local<v8::Value> coordinate = coordinates_array->Get(i);
if (!coordinate->IsArray())
{
Nan::ThrowError("Coordinates must be an array of (lon/lat) pairs");
return resulting_coordinates;
}
v8::Local<v8::Array> coordinate_pair = v8::Local<v8::Array>::Cast(coordinate);
if (coordinate_pair->Length() != 2)
{
Nan::ThrowError("Coordinates must be an array of (lon/lat) pairs");
return resulting_coordinates;
}
if (!coordinate_pair->Get(0)->IsNumber() || !coordinate_pair->Get(1)->IsNumber())
{
Nan::ThrowError("Each member of a coordinate pair must be a number");
return resulting_coordinates;
}
double lon = coordinate_pair->Get(0)->NumberValue();
double lat = coordinate_pair->Get(1)->NumberValue();
if (std::isnan(lon) || std::isnan(lat) || std::isinf(lon) || std::isinf(lat))
{
Nan::ThrowError("Lng/Lat coordinates must be valid numbers");
return resulting_coordinates;
}
if (lon > 180 || lon < -180 || lat > 90 || lat < -90)
{
Nan::ThrowError("Lng/Lat coordinates must be within world bounds "
"(-180 < lng < 180, -90 < lat < 90)");
return resulting_coordinates;
}
temp_coordinates.emplace_back(osrm::util::FloatLongitude{std::move(lon)},
osrm::util::FloatLatitude{std::move(lat)});
}
resulting_coordinates = boost::make_optional(std::move(temp_coordinates));
return resulting_coordinates;
}
// Parses all the non-service specific parameters
template <typename ParamType>
inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
ParamType &params,
bool requires_multiple_coordinates)
{
Nan::HandleScope scope;
if (args.Length() < 2)
{
Nan::ThrowTypeError("Two arguments required");
return false;
}
if (!args[0]->IsObject())
{
Nan::ThrowTypeError("First arg must be an object");
return false;
}
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
v8::Local<v8::Value> coordinates = obj->Get(Nan::New("coordinates").ToLocalChecked());
if (coordinates->IsUndefined())
{
Nan::ThrowError("Must provide a coordinates property");
return false;
}
else if (coordinates->IsArray())
{
auto coordinates_array = v8::Local<v8::Array>::Cast(coordinates);
if (coordinates_array->Length() < 2 && requires_multiple_coordinates)
{
Nan::ThrowError("At least two coordinates must be provided");
return false;
}
else if (!requires_multiple_coordinates && coordinates_array->Length() != 1)
{
Nan::ThrowError("Exactly one coordinate pair must be provided");
return false;
}
auto maybe_coordinates = parseCoordinateArray(coordinates_array);
if (maybe_coordinates)
{
std::copy(maybe_coordinates->begin(),
maybe_coordinates->end(),
std::back_inserter(params->coordinates));
}
else
{
return false;
}
}
else if (!coordinates->IsUndefined())
{
BOOST_ASSERT(!coordinates->IsArray());
Nan::ThrowError("Coordinates must be an array of (lon/lat) pairs");
return false;
}
if (obj->Has(Nan::New("bearings").ToLocalChecked()))
{
v8::Local<v8::Value> bearings = obj->Get(Nan::New("bearings").ToLocalChecked());
if (!bearings->IsArray())
{
Nan::ThrowError("Bearings must be an array of arrays of numbers");
return false;
}
auto bearings_array = v8::Local<v8::Array>::Cast(bearings);
if (bearings_array->Length() != params->coordinates.size())
{
Nan::ThrowError("Bearings array must have the same length as coordinates array");
return false;
}
for (uint32_t i = 0; i < bearings_array->Length(); ++i)
{
v8::Local<v8::Value> bearing_raw = bearings_array->Get(i);
if (bearing_raw->IsNull())
{
params->bearings.emplace_back();
}
else if (bearing_raw->IsArray())
{
auto bearing_pair = v8::Local<v8::Array>::Cast(bearing_raw);
if (bearing_pair->Length() == 2)
{
if (!bearing_pair->Get(0)->IsNumber() || !bearing_pair->Get(1)->IsNumber())
{
Nan::ThrowError("Bearing values need to be numbers in range 0..360");
return false;
}
const auto bearing = static_cast<short>(bearing_pair->Get(0)->NumberValue());
const auto range = static_cast<short>(bearing_pair->Get(1)->NumberValue());
if (bearing < 0 || bearing > 360 || range < 0 || range > 180)
{
Nan::ThrowError("Bearing values need to be in range 0..360, 0..180");
return false;
}
params->bearings.push_back(osrm::Bearing{bearing, range});
}
else
{
Nan::ThrowError("Bearing must be an array of [bearing, range] or null");
return false;
}
}
else
{
Nan::ThrowError("Bearing must be an array of [bearing, range] or null");
return false;
}
}
}
if (obj->Has(Nan::New("hints").ToLocalChecked()))
{
v8::Local<v8::Value> hints = obj->Get(Nan::New("hints").ToLocalChecked());
if (!hints->IsArray())
{
Nan::ThrowError("Hints must be an array of strings/null");
return false;
}
v8::Local<v8::Array> hints_array = v8::Local<v8::Array>::Cast(hints);
if (hints_array->Length() != params->coordinates.size())
{
Nan::ThrowError("Hints array must have the same length as coordinates array");
return false;
}
for (uint32_t i = 0; i < hints_array->Length(); ++i)
{
v8::Local<v8::Value> hint = hints_array->Get(i);
if (hint->IsString())
{
if (hint->ToString()->Length() == 0)
{
Nan::ThrowError("Hint cannot be an empty string");
return false;
}
params->hints.push_back(
osrm::engine::Hint::FromBase64(*v8::String::Utf8Value(hint)));
}
else if (hint->IsNull())
{
params->hints.emplace_back();
}
else
{
Nan::ThrowError("Hint must be null or string");
return false;
}
}
}
if (obj->Has(Nan::New("radiuses").ToLocalChecked()))
{
v8::Local<v8::Value> radiuses = obj->Get(Nan::New("radiuses").ToLocalChecked());
if (!radiuses->IsArray())
{
Nan::ThrowError("Radiuses must be an array of non-negative doubles or null");
return false;
}
v8::Local<v8::Array> radiuses_array = v8::Local<v8::Array>::Cast(radiuses);
if (radiuses_array->Length() != params->coordinates.size())
{
Nan::ThrowError("Radiuses array must have the same length as coordinates array");
return false;
}
for (uint32_t i = 0; i < radiuses_array->Length(); ++i)
{
v8::Local<v8::Value> radius = radiuses_array->Get(i);
if (radius->IsNull())
{
params->radiuses.emplace_back();
}
else if (radius->IsNumber() && radius->NumberValue() >= 0)
{
params->radiuses.push_back(static_cast<double>(radius->NumberValue()));
}
else
{
Nan::ThrowError("Radius must be non-negative double or null");
return false;
}
}
}
if (obj->Has(Nan::New("generate_hints").ToLocalChecked()))
{
v8::Local<v8::Value> generate_hints = obj->Get(Nan::New("generate_hints").ToLocalChecked());
if (!generate_hints->IsBoolean())
{
Nan::ThrowError("generate_hints must be of type Boolean");
return false;
}
params->generate_hints = generate_hints->BooleanValue();
}
return true;
}
template <typename ParamType>
inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &params)
{
if (obj->Has(Nan::New("steps").ToLocalChecked()))
{
auto steps = obj->Get(Nan::New("steps").ToLocalChecked());
if (steps->IsBoolean())
{
params->steps = steps->BooleanValue();
}
else
{
Nan::ThrowError("'steps' param must be a boolean");
return false;
}
}
if (obj->Has(Nan::New("annotations").ToLocalChecked()))
{
auto annotations = obj->Get(Nan::New("annotations").ToLocalChecked());
if (annotations->IsBoolean())
{
params->annotations = annotations->BooleanValue();
}
else if (annotations->IsArray())
{
v8::Local<v8::Array> annotations_array = v8::Local<v8::Array>::Cast(annotations);
for (std::size_t i = 0; i < annotations_array->Length(); i++)
{
const Nan::Utf8String annotations_utf8str(annotations_array->Get(i));
std::string annotations_str{*annotations_utf8str,
*annotations_utf8str + annotations_utf8str.length()};
if (annotations_str == "duration")
{
params->annotations_type =
params->annotations_type | osrm::RouteParameters::AnnotationsType::Duration;
}
else if (annotations_str == "nodes")
{
params->annotations_type =
params->annotations_type | osrm::RouteParameters::AnnotationsType::Nodes;
}
else if (annotations_str == "distance")
{
params->annotations_type =
params->annotations_type | osrm::RouteParameters::AnnotationsType::Distance;
}
else if (annotations_str == "weight")
{
params->annotations_type =
params->annotations_type | osrm::RouteParameters::AnnotationsType::Weight;
}
else if (annotations_str == "datasources")
{
params->annotations_type = params->annotations_type |
osrm::RouteParameters::AnnotationsType::Datasources;
}
else if (annotations_str == "speed")
{
params->annotations_type =
params->annotations_type | osrm::RouteParameters::AnnotationsType::Speed;
}
else
{
Nan::ThrowError("this 'annotations' param is not supported");
return false;
}
}
}
else
{
Nan::ThrowError("this 'annotations' param is not supported");
return false;
}
}
if (obj->Has(Nan::New("geometries").ToLocalChecked()))
{
v8::Local<v8::Value> geometries = obj->Get(Nan::New("geometries").ToLocalChecked());
if (!geometries->IsString())
{
Nan::ThrowError("Geometries must be a string: [polyline, polyline6, geojson]");
return false;
}
const Nan::Utf8String geometries_utf8str(geometries);
std::string geometries_str{*geometries_utf8str,
*geometries_utf8str + geometries_utf8str.length()};
if (geometries_str == "polyline")
{
params->geometries = osrm::RouteParameters::GeometriesType::Polyline;
}
else if (geometries_str == "polyline6")
{
params->geometries = osrm::RouteParameters::GeometriesType::Polyline6;
}
else if (geometries_str == "geojson")
{
params->geometries = osrm::RouteParameters::GeometriesType::GeoJSON;
}
else
{
Nan::ThrowError("'geometries' param must be one of [polyline, polyline6, geojson]");
return false;
}
}
if (obj->Has(Nan::New("overview").ToLocalChecked()))
{
v8::Local<v8::Value> overview = obj->Get(Nan::New("overview").ToLocalChecked());
if (!overview->IsString())
{
Nan::ThrowError("Overview must be a string: [simplified, full, false]");
return false;
}
const Nan::Utf8String overview_utf8str(overview);
std::string overview_str{*overview_utf8str, *overview_utf8str + overview_utf8str.length()};
if (overview_str == "simplified")
{
params->overview = osrm::RouteParameters::OverviewType::Simplified;
}
else if (overview_str == "full")
{
params->overview = osrm::RouteParameters::OverviewType::Full;
}
else if (overview_str == "false")
{
params->overview = osrm::RouteParameters::OverviewType::False;
}
else
{
Nan::ThrowError("'overview' param must be one of [simplified, full, false]");
return false;
}
}
return true;
}
inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
route_parameters_ptr params = boost::make_unique<osrm::RouteParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return route_parameters_ptr();
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
if (obj->Has(Nan::New("continue_straight").ToLocalChecked()))
{
auto value = obj->Get(Nan::New("continue_straight").ToLocalChecked());
if (!value->IsBoolean() && !value->IsNull())
{
Nan::ThrowError("'continue_straight' parama must be boolean or null");
}
if (value->IsBoolean())
{
params->continue_straight = value->BooleanValue();
}
}
if (obj->Has(Nan::New("alternatives").ToLocalChecked()))
{
auto value = obj->Get(Nan::New("alternatives").ToLocalChecked());
if (!value->IsBoolean())
{
Nan::ThrowError("'alternatives' parama must be boolean");
}
params->alternatives = value->BooleanValue();
}
bool parsedSuccessfully = parseCommonParameters(obj, params);
if (!parsedSuccessfully)
{
return route_parameters_ptr();
}
return params;
}
inline tile_parameters_ptr
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
{
tile_parameters_ptr params = boost::make_unique<osrm::TileParameters>();
if (args.Length() < 2)
{
Nan::ThrowTypeError("Coordinate object and callback required");
return tile_parameters_ptr();
}
if (!args[0]->IsArray())
{
Nan::ThrowTypeError("Parameter must be an array [x, y, z]");
return tile_parameters_ptr();
}
v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[0]);
if (array->Length() != 3)
{
Nan::ThrowTypeError("Parameter must be an array [x, y, z]");
return tile_parameters_ptr();
}
v8::Local<v8::Value> x = array->Get(0);
v8::Local<v8::Value> y = array->Get(1);
v8::Local<v8::Value> z = array->Get(2);
if (!x->IsUint32() && !x->IsUndefined())
{
Nan::ThrowError("Tile x coordinate must be unsigned interger");
return tile_parameters_ptr();
}
if (!y->IsUint32() && !y->IsUndefined())
{
Nan::ThrowError("Tile y coordinate must be unsigned interger");
return tile_parameters_ptr();
}
if (!z->IsUint32() && !z->IsUndefined())
{
Nan::ThrowError("Tile z coordinate must be unsigned interger");
return tile_parameters_ptr();
}
params->x = x->Uint32Value();
params->y = y->Uint32Value();
params->z = z->Uint32Value();
if (!params->IsValid())
{
Nan::ThrowError("Invalid tile coordinates");
return tile_parameters_ptr();
}
return params;
}
inline nearest_parameters_ptr
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
nearest_parameters_ptr params = boost::make_unique<osrm::NearestParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return nearest_parameters_ptr();
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
if (obj->Has(Nan::New("number").ToLocalChecked()))
{
v8::Local<v8::Value> number = obj->Get(Nan::New("number").ToLocalChecked());
if (!number->IsUint32())
{
Nan::ThrowError("Number must be an integer greater than or equal to 1");
return nearest_parameters_ptr();
}
else
{
unsigned number_value = static_cast<unsigned>(number->NumberValue());
if (number_value < 1)
{
Nan::ThrowError("Number must be an integer greater than or equal to 1");
return nearest_parameters_ptr();
}
params->number_of_results = static_cast<unsigned>(number->NumberValue());
}
}
return params;
}
inline table_parameters_ptr
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
table_parameters_ptr params = boost::make_unique<osrm::TableParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return table_parameters_ptr();
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
if (obj->Has(Nan::New("sources").ToLocalChecked()))
{
v8::Local<v8::Value> sources = obj->Get(Nan::New("sources").ToLocalChecked());
if (!sources->IsArray())
{
Nan::ThrowError("Sources must be an array of indices (or undefined)");
return table_parameters_ptr();
}
v8::Local<v8::Array> sources_array = v8::Local<v8::Array>::Cast(sources);
for (uint32_t i = 0; i < sources_array->Length(); ++i)
{
v8::Local<v8::Value> source = sources_array->Get(i);
if (source->IsUint32())
{
size_t source_value = static_cast<size_t>(source->NumberValue());
if (source_value > params->coordinates.size())
{
Nan::ThrowError(
"Source indices must be less than or equal to the number of coordinates");
return table_parameters_ptr();
}
params->sources.push_back(static_cast<size_t>(source->NumberValue()));
}
else
{
Nan::ThrowError("Source must be an integer");
return table_parameters_ptr();
}
}
}
if (obj->Has(Nan::New("destinations").ToLocalChecked()))
{
v8::Local<v8::Value> destinations = obj->Get(Nan::New("destinations").ToLocalChecked());
if (!destinations->IsArray())
{
Nan::ThrowError("Destinations must be an array of indices (or undefined)");
return table_parameters_ptr();
}
v8::Local<v8::Array> destinations_array = v8::Local<v8::Array>::Cast(destinations);
for (uint32_t i = 0; i < destinations_array->Length(); ++i)
{
v8::Local<v8::Value> destination = destinations_array->Get(i);
if (destination->IsUint32())
{
size_t destination_value = static_cast<size_t>(destination->NumberValue());
if (destination_value > params->coordinates.size())
{
Nan::ThrowError("Destination indices must be less than or equal to the number "
"of coordinates");
return table_parameters_ptr();
}
params->destinations.push_back(static_cast<size_t>(destination->NumberValue()));
}
else
{
Nan::ThrowError("Destination must be an integer");
return table_parameters_ptr();
}
}
}
return params;
}
inline trip_parameters_ptr
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
trip_parameters_ptr params = boost::make_unique<osrm::TripParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return trip_parameters_ptr();
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
bool parsedSuccessfully = parseCommonParameters(obj, params);
if (!parsedSuccessfully)
{
return trip_parameters_ptr();
}
if (obj->Has(Nan::New("roundtrip").ToLocalChecked()))
{
auto roundtrip = obj->Get(Nan::New("roundtrip").ToLocalChecked());
if (roundtrip->IsBoolean())
{
params->roundtrip = roundtrip->BooleanValue();
}
else
{
Nan::ThrowError("'roundtrip' param must be a boolean");
return trip_parameters_ptr();
}
}
if (obj->Has(Nan::New("source").ToLocalChecked()))
{
v8::Local<v8::Value> source = obj->Get(Nan::New("source").ToLocalChecked());
if (!source->IsString())
{
Nan::ThrowError("Source must be a string: [any, first]");
return trip_parameters_ptr();
}
std::string source_str = *v8::String::Utf8Value(source);
if (source_str == "first")
{
params->source = osrm::TripParameters::SourceType::First;
}
else if (source_str == "any")
{
params->source = osrm::TripParameters::SourceType::Any;
}
else
{
Nan::ThrowError("'source' param must be one of [any, first]");
return trip_parameters_ptr();
}
}
if (obj->Has(Nan::New("destination").ToLocalChecked()))
{
v8::Local<v8::Value> destination = obj->Get(Nan::New("destination").ToLocalChecked());
if (!destination->IsString())
{
Nan::ThrowError("Destination must be a string: [any, last]");
return trip_parameters_ptr();
}
std::string destination_str = *v8::String::Utf8Value(destination);
if (destination_str == "last")
{
params->destination = osrm::TripParameters::DestinationType::Last;
}
else if (destination_str == "any")
{
params->destination = osrm::TripParameters::DestinationType::Any;
}
else
{
Nan::ThrowError("'destination' param must be one of [any, last]");
return trip_parameters_ptr();
}
}
return params;
}
inline match_parameters_ptr
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
match_parameters_ptr params = boost::make_unique<osrm::MatchParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return match_parameters_ptr();
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
if (obj->Has(Nan::New("timestamps").ToLocalChecked()))
{
v8::Local<v8::Value> timestamps = obj->Get(Nan::New("timestamps").ToLocalChecked());
if (!timestamps->IsArray())
{
Nan::ThrowError("Timestamps must be an array of integers (or undefined)");
return match_parameters_ptr();
}
v8::Local<v8::Array> timestamps_array = v8::Local<v8::Array>::Cast(timestamps);
if (params->coordinates.size() != timestamps_array->Length())
{
Nan::ThrowError("Timestamp array must have the same size as the coordinates "
"array");
return match_parameters_ptr();
}
for (uint32_t i = 0; i < timestamps_array->Length(); ++i)
{
v8::Local<v8::Value> timestamp = timestamps_array->Get(i);
if (!timestamp->IsNumber())
{
Nan::ThrowError("Timestamps array items must be numbers");
return match_parameters_ptr();
}
params->timestamps.emplace_back(static_cast<unsigned>(timestamp->NumberValue()));
}
}
bool parsedSuccessfully = parseCommonParameters(obj, params);
if (!parsedSuccessfully)
{
return match_parameters_ptr();
}
return params;
}
} // ns node_osrm
#endif

0
lib/binding/.gitkeep Normal file
View File

2
lib/index.js Normal file
View File

@ -0,0 +1,2 @@
var OSRM = module.exports = require('./binding/node-osrm.node').OSRM;
OSRM.version = require('../package.json').version;

View File

@ -1,6 +1,6 @@
{
"name": "osrm-backend-test-suite",
"version": "0.0.0",
"name": "osrm",
"version": "5.7.0",
"private": true,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {
@ -12,7 +12,11 @@
"polyline": "^0.2.0",
"request": "^2.69.0",
"rimraf": "^2.5.4",
"xmlbuilder": "^4.2.1"
"xmlbuilder": "^4.2.1",
"nan": "^2.1.0",
"node-cmake": "^1.2.1",
"node-pre-gyp": "~0.6.30"
},
"bin": {
"cucumber": "./node_modules/cucumber/bin/cucumber.js"
@ -28,7 +32,10 @@
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
"clean-test": "rm -rf test/cache",
"cucumber": "./node_modules/cucumber/bin/cucumber.js",
"build-api-docs": "./scripts/build_api_docs.sh"
"build-api-docs": "./scripts/build_api_docs.sh",
"preinstall": "npm install node-pre-gyp",
"install": "node-pre-gyp install --fallback-to-build=false"
},
"repository": {
"type": "git",
@ -45,6 +52,17 @@
},
"devDependencies": {
"docbox": "^1.0.2",
"eslint": "^2.4.0"
"eslint": "^2.4.0",
"aws-sdk": "~2.0.31",
"tape": "^4.2.2"
},
"main": "lib/index.js",
"binary": {
"module_name": "node-osrm",
"module_path": "./lib/binding/",
"host": "https://mapbox-node-binary.s3.amazonaws.com",
"remote_path": "./{name}/v{version}/{configuration}/",
"package_name": "{node_abi}-{platform}-{arch}.tar.gz"
}
}

View File

@ -51,8 +51,8 @@ else if (process.argv.length > 2 && process.argv[2] == "dc")
}
else if (process.argv.length > 2)
{
let monaco_poly_path = process.argv[2];
let poly_data = fs.readFileSync(monaco_poly_path, 'utf-8');
let poly_path = process.argv[2];
let poly_data = fs.readFileSync(poly_path, 'utf-8');
// lets assume there is only one ring
// cut of name and ring number and the two END statements

99
scripts/travis/build.sh Executable file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -eu
set -o pipefail
# defaults
export ENABLE_COVERAGE=${ENABLE_COVERAGE:-"Off"}
export BUILD_TYPE=${BUILD_TYPE:-"Release"}
export NODE=${NODE:-4}
export CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export DEPS_DIR="$(pwd)/deps"
export PATH=${DEPS_DIR}/bin:${PATH}
mkdir -p ${DEPS_DIR}
export CLANG_VERSION="${CLANG_VERSION:-4.0.0}"
export CCACHE_VERSION=3.3.1
export CMAKE_VERSION=3.7.2
source ${CURRENT_DIR}/travis_helper.sh
# ensure we start inside the root directory (two level up)
cd ${CURRENT_DIR}/../../
if [[ ! $(which wget) ]]; then
echo "echo wget must be installed";
exit 1;
fi;
SYSTEM_NAME=$(uname -s)
if [[ "${SYSTEM_NAME}" == "Darwin" ]]; then
OS_NAME="osx"
elif [[ "${SYSTEM_NAME}" == "Linux" ]]; then
OS_NAME="linux"
fi
# FIXME This should be replaced by proper calls to mason but we currently have a chicken-egg problem
# since we rely on osrm-backend to ship mason for us. Once we merged this into osrm-backend this will not be needed.
CMAKE_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
echo "Downloading cmake from ${CMAKE_URL} ..."
wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
CCACHE_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/ccache/${CCACHE_VERSION}.tar.gz"
echo "Downloading ccache from ${CCACHE_URL} ..."
wget --quiet -O - ${CCACHE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
# install clang for linux but use the xcode version on OSX
if [[ "${OS_NAME}" != "osx" ]]; then
CLANG_URL="https://s3.amazonaws.com/mason-binaries/${OS_NAME}-x86_64/clang++/${CLANG_VERSION}.tar.gz"
echo "Downloading clang from ${CLANG_URL} ..."
wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
export CCOMPILER='clang'
export CXXCOMPILER='clang++'
export CC='clang'
export CXX='clang++'
fi
if [[ "${OS_NAME}" == "osx" ]]; then
if [[ -f /etc/sysctl.conf ]] && [[ $(grep shmmax /etc/sysctl.conf) ]]; then
echo "Note: found shmmax setting in /etc/sysctl.conf, not modifying"
else
echo "WARNING: Did not find shmmax setting in /etc/sysctl.conf, adding now (requires sudo and restarting)..."
sudo sysctl -w kern.sysv.shmmax=4294967296
sudo sysctl -w kern.sysv.shmall=1048576
sudo sysctl -w kern.sysv.shmseg=128
fi
fi
echo "Now build node-osrm and dependencies"
export VERBOSE=1
if [[ "${ENABLE_COVERAGE}" == "On" ]]; then
mapbox_time "make" make -j4 coverage
else
mkdir -p build
pushd build
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On
mapbox_time "make" make -j4
popd
fi
## run tests, with backtrace support
#if [[ "${OS_NAME}" == "linux" ]]; then
# ulimit -c unlimited -S
# RESULT=0
# mapbox_time "make-test" make tests || RESULT=$?
# for i in $(find ./ -maxdepth 1 -name 'core*' -print);
# do gdb $(which node) $i -ex "thread apply all bt" -ex "set pagination 0" -batch;
# done;
# if [[ ${RESULT} != 0 ]]; then exit $RESULT; fi
#else
# # todo: coredump support on OS X
# RESULT=0
# mapbox_time "make-test" make tests || RESULT=$?
# if [[ ${RESULT} != 0 ]]; then exit $RESULT; fi
#fi
set +eu
set +o pipefail

27
scripts/travis/is_pr_merge.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
set -eu pipefail
: '
This script is designed to detect if a gitsha represents a normal
push commit (to any branch) or whether it represents travis attempting
to merge between the origin and the upstream branch.
For more details see: https://docs.travis-ci.com/user/pull-requests
'
# Get the commit message via git log
# This should always be the exact text the developer provided
COMMIT_LOG=$(git log --format=%B --no-merges -n 1 | tr -d '\n')
# Get the commit message via git show
# If the gitsha represents a merge then this will
# look something like "Merge e3b1981 into 615d2a3"
# Otherwise it will be the same as the "git log" output
COMMIT_SHOW=$(git show -s --format=%B | tr -d '\n')
if [[ "${COMMIT_LOG}" != "${COMMIT_SHOW}" ]]; then
echo true
fi

51
scripts/travis/publish.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/bash
set -eu
set -o pipefail
# should be set for debug builds
export NPM_FLAGS=${NPM_FLAGS:-}
echo "node version is:"
which node
node -v
echo "dumping binary meta..."
./node_modules/.bin/node-pre-gyp reveal ${NPM_FLAGS}
# enforce that binary has proper ORIGIN flags so that
# it can portably find libtbb.so in the same directory
if [[ $(uname -s) == 'Linux' ]]; then
readelf -d ./lib/binding/node-osrm.node > readelf-output.txt
if grep -q 'Flags: ORIGIN' readelf-output.txt; then
echo "Found ORIGIN flag in readelf output"
cat readelf-output.txt
else
echo "*** Error: Could not found ORIGIN flag in readelf output"
cat readelf-output.txt
exit 1
fi
fi
echo "determining publishing status..."
if [[ $(./scripts/travis/is_pr_merge.sh) ]]; then
echo "Skipping publishing because this is a PR merge commit"
else
echo "This is a push commit, continuing to package..."
./node_modules/.bin/node-pre-gyp package ${NPM_FLAGS}
export COMMIT_MESSAGE=$(git log --format=%B --no-merges | head -n 1 | tr -d '\n')
echo "Commit message: ${COMMIT_MESSAGE}"
if [[ ${COMMIT_MESSAGE} =~ "[publish binary]" ]]; then
echo "Publishing"
./node_modules/.bin/node-pre-gyp publish ${NPM_FLAGS}
elif [[ ${COMMIT_MESSAGE} =~ "[republish binary]" ]]; then
echo "*** Error: Republishing is disallowed for this repository"
exit 1
#./node_modules/.bin/node-pre-gyp unpublish publish ${NPM_FLAGS}
else
echo "Skipping publishing"
fi;
fi

View File

@ -0,0 +1,75 @@
#!/usr/bin/env bash
# This script is sourced, so do not set -e or -o pipefail here. Doing so would
# bleed into Travis' wrapper script, which messes with their workflow, e.g.
# preventing after_failure scripts to be triggered.
function mapbox_time_start {
local name=$1
mapbox_timer_name=$name
mapbox_fold start $name
mapbox_timer_id=$(printf %08x $(( RANDOM * RANDOM )))
eval "mapbox_start_time_$mapbox_timer_id=$(mapbox_nanoseconds)"
echo -en "travis_time:start:$mapbox_timer_id\n"
}
function mapbox_time_finish {
local name=${1:-$mapbox_timer_name}
local timer_id=${2:-$mapbox_timer_id}
local timer_start="mapbox_start_time_$timer_id"
eval local start_time=\${$timer_start}
local end_time=$(mapbox_nanoseconds)
local duration=$(($end_time-$start_time))
echo -en "travis_time:end:$timer_id:start=$start_time,finish=$end_time,duration=$duration\n"
}
function mapbox_time {
local name=$1 ; shift
mapbox_time_start $name
local timer_id=$mapbox_timer_id
echo "\$ $@"
# note: we capture the return code here
# so that we can ensure mapbox_time_finish is called
# and an error is trickled up correctly
local RESULT=0
$@ || RESULT=$?
mapbox_time_finish $name $timer_id
if [[ ${RESULT} != 0 ]]; then
echo "$name failed with ${RESULT}"
# note: we use false here instead of exit this this script is sourced
# and exit would abort the shell which we don't want
false
else
mapbox_fold end $name
fi
}
function mapbox_fold {
local action=$1
local name=$2
local ANSI_CLEAR="\e[0m"
echo -en "travis_fold:${action}:${name}\r${ANSI_CLEAR}"
}
function mapbox_nanoseconds {
local cmd="date"
local format="+%s%N"
local os=$(uname -s)
if hash gdate > /dev/null 2>&1; then
cmd="gdate" # use gdate if available
elif [[ "$os" = Darwin ]]; then
format="+%s000000000" # fallback to second precision on darwin (does not support %N)
fi
$cmd -u $format
}
export JOBS
export -f mapbox_fold
export -f mapbox_nanoseconds
export -f mapbox_time
export -f mapbox_time_start
export -f mapbox_time_finish

View File

@ -36,7 +36,7 @@ int main(int argc, const char *argv[]) try
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
OSRM osrm{config};
// Route in monaco
// Match traces to the road network in our Berlin test dataset
MatchParameters params;
params.overview = RouteParameters::OverviewType::False;
params.steps = false;
@ -45,170 +45,123 @@ int main(int argc, const char *argv[]) try
using osrm::util::FloatLatitude;
using osrm::util::FloatLongitude;
// Grab trace, or: go to geojson.io, create linestring.
// Extract coordinates: jq '.features[].geometry.coordinates[]' coordinates.json
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.422176599502563}, FloatLatitude{43.73754595167546}});
FloatCoordinate{FloatLongitude{13.410401344299316}, FloatLatitude{52.522749270442254}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.421715259552002}, FloatLatitude{43.73744517900973}});
FloatCoordinate{FloatLongitude{13.410615921020508}, FloatLatitude{52.52284066124772}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.421489953994752}, FloatLatitude{43.73738316497729}});
FloatCoordinate{FloatLongitude{13.410787582397461}, FloatLatitude{52.522932051863044}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.421286106109619}, FloatLatitude{43.737274640266}});
FloatCoordinate{FloatLongitude{13.411259651184082}, FloatLatitude{52.52333677944541}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420910596847533}, FloatLatitude{43.73714285999499}});
FloatCoordinate{FloatLongitude{13.411538600921629}, FloatLatitude{52.52341511338546}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420696020126342}, FloatLatitude{43.73699557581948}});
FloatCoordinate{FloatLongitude{13.411903381347656}, FloatLatitude{52.52374150329884}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.42049217224121}, FloatLatitude{43.73690255404829}});
FloatCoordinate{FloatLongitude{13.412246704101562}, FloatLatitude{52.523950391570665}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420309782028198}, FloatLatitude{43.73672426191624}});
FloatCoordinate{FloatLongitude{13.410637378692625}, FloatLatitude{52.52398955801103}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420159578323363}, FloatLatitude{43.7366622471372}});
FloatCoordinate{FloatLongitude{13.409242630004881}, FloatLatitude{52.52413316799366}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420148849487305}, FloatLatitude{43.736623487867654}});
FloatCoordinate{FloatLongitude{13.407998085021973}, FloatLatitude{52.52448566323317}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419934272766113}, FloatLatitude{43.73647620241466}});
FloatCoordinate{FloatLongitude{13.40705394744873}, FloatLatitude{52.52474676899426}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419805526733398}, FloatLatitude{43.736228141885455}});
FloatCoordinate{FloatLongitude{13.406410217285156}, FloatLatitude{52.5249948180297}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419601678848267}, FloatLatitude{43.736142870841206}});
FloatCoordinate{FloatLongitude{13.406989574432373}, FloatLatitude{52.525686736883024}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419376373291015}, FloatLatitude{43.735956824504974}});
FloatCoordinate{FloatLongitude{13.407375812530518}, FloatLatitude{52.52628726139225}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419247627258301}, FloatLatitude{43.73574752168583}});
FloatCoordinate{FloatLongitude{13.406217098236084}, FloatLatitude{52.52663973934549}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419043779373169}, FloatLatitude{43.73566224995717}});
FloatCoordinate{FloatLongitude{13.405036926269531}, FloatLatitude{52.52696610529863}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418732643127442}, FloatLatitude{43.735406434042645}});
FloatCoordinate{FloatLongitude{13.404350280761717}, FloatLatitude{52.52717497823596}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418657541275024}, FloatLatitude{43.735321161828274}});
FloatCoordinate{FloatLongitude{13.404221534729004}, FloatLatitude{52.5265222470087}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418593168258667}, FloatLatitude{43.73521263337983}});
FloatCoordinate{FloatLongitude{13.40383529663086}, FloatLatitude{52.526039219655445}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418367862701416}, FloatLatitude{43.73508084857086}});
FloatCoordinate{FloatLongitude{13.402740955352783}, FloatLatitude{52.526300316181675}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418346405029297}, FloatLatitude{43.73484828643578}});
FloatCoordinate{FloatLongitude{13.401474952697754}, FloatLatitude{52.52666584871098}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4180567264556885}, FloatLatitude{43.734437424456566}});
FloatCoordinate{FloatLongitude{13.400874137878418}, FloatLatitude{52.527370795712564}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417809963226318}, FloatLatitude{43.73414284243448}});
FloatCoordinate{FloatLongitude{13.400616645812988}, FloatLatitude{52.52780159108807}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417863607406615}, FloatLatitude{43.73375523230292}});
FloatCoordinate{FloatLongitude{13.399865627288817}, FloatLatitude{52.52756661231615}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417809963226318}, FloatLatitude{43.73386376339265}});
FloatCoordinate{FloatLongitude{13.399114608764648}, FloatLatitude{52.52744912245876}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417895793914795}, FloatLatitude{43.73365445325776}});
FloatCoordinate{FloatLongitude{13.39802026748657}, FloatLatitude{52.527266359833675}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418067455291747}, FloatLatitude{43.73343739012297}});
FloatCoordinate{FloatLongitude{13.398470878601072}, FloatLatitude{52.52648308282661}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41803526878357}, FloatLatitude{43.73319706930599}});
FloatCoordinate{FloatLongitude{13.398964405059813}, FloatLatitude{52.52538647154948}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418024539947509}, FloatLatitude{43.73295674752463}});
FloatCoordinate{FloatLongitude{13.398363590240479}, FloatLatitude{52.52542563670941}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417906522750854}, FloatLatitude{43.73284821479115}});
FloatCoordinate{FloatLongitude{13.39780569076538}, FloatLatitude{52.525347306354654}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417917251586914}, FloatLatitude{43.7327551865773}});
FloatCoordinate{FloatLongitude{13.397247791290283}, FloatLatitude{52.525190645226104}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417434453964233}, FloatLatitude{43.73281720540258}});
FloatCoordinate{FloatLongitude{13.396217823028564}, FloatLatitude{52.52494259729653}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4173808097839355}, FloatLatitude{43.73307303237796}});
FloatCoordinate{FloatLongitude{13.395531177520752}, FloatLatitude{52.52452482919627}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41750955581665}, FloatLatitude{43.73328234454499}});
FloatCoordinate{FloatLongitude{13.39482307434082}, FloatLatitude{52.524472607904364}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417563199996948}, FloatLatitude{43.73352266501975}});
FloatCoordinate{FloatLongitude{13.39359998703003}, FloatLatitude{52.5246814926995}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41750955581665}, FloatLatitude{43.733770736756355}});
FloatCoordinate{FloatLongitude{13.392891883850098}, FloatLatitude{52.52490343170594}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417466640472412}, FloatLatitude{43.73409632935116}});
FloatCoordinate{FloatLongitude{13.392398357391357}, FloatLatitude{52.5239765025348}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417230606079102}, FloatLatitude{43.73428238146768}});
FloatCoordinate{FloatLongitude{13.391926288604736}, FloatLatitude{52.52310177678706}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41724133491516}, FloatLatitude{43.73405756842078}});
FloatCoordinate{FloatLongitude{13.39184045791626}, FloatLatitude{52.52222703362077}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4169838428497314}, FloatLatitude{43.73449168940785}});
FloatCoordinate{FloatLongitude{13.39184045791626}, FloatLatitude{52.521169485041774}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41701602935791}, FloatLatitude{43.734615723397525}});
FloatCoordinate{FloatLongitude{13.39184045791626}, FloatLatitude{52.52039915585348}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41704821586609}, FloatLatitude{43.73487929477265}});
FloatCoordinate{FloatLongitude{13.39205503463745}, FloatLatitude{52.519681040207885}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41725206375122}, FloatLatitude{43.734949063471895}});
FloatCoordinate{FloatLongitude{13.392269611358643}, FloatLatitude{52.51900208371135}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4173808097839355}, FloatLatitude{43.73533666587628}});
FloatCoordinate{FloatLongitude{13.392527103424072}, FloatLatitude{52.51812725890996}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41750955581665}, FloatLatitude{43.735623490040375}});
FloatCoordinate{FloatLongitude{13.392677307128904}, FloatLatitude{52.51750050804369}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417799234390259}, FloatLatitude{43.73577852955704}});
FloatCoordinate{FloatLongitude{13.393385410308838}, FloatLatitude{52.51735687637764}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4180781841278085}, FloatLatitude{43.735972328388435}});
FloatCoordinate{FloatLongitude{13.394951820373535}, FloatLatitude{52.517474393230245}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41850733757019}, FloatLatitude{43.73608860738618}});
FloatCoordinate{FloatLongitude{13.396711349487305}, FloatLatitude{52.51735687637764}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418850660324096}, FloatLatitude{43.736228141885455}});
FloatCoordinate{FloatLongitude{13.398127555847168}, FloatLatitude{52.517696368649815}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419086694717407}, FloatLatitude{43.73636767605958}});
FloatCoordinate{FloatLongitude{13.399629592895508}, FloatLatitude{52.51773554066627}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419333457946777}, FloatLatitude{43.73664674343239}});
FloatCoordinate{FloatLongitude{13.400981426239014}, FloatLatitude{52.51829700239765}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419633865356444}, FloatLatitude{43.73676302112054}});
FloatCoordinate{FloatLongitude{13.403105735778809}, FloatLatitude{52.51887151395141}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419784069061279}, FloatLatitude{43.737096349241845}});
FloatCoordinate{FloatLongitude{13.40355634689331}, FloatLatitude{52.51966798345114}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.420030832290649}, FloatLatitude{43.73720487427631}});
FloatCoordinate{FloatLongitude{13.404908180236816}, FloatLatitude{52.52007274110608}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419601678848267}, FloatLatitude{43.73708084564945}});
FloatCoordinate{FloatLongitude{13.40555191040039}, FloatLatitude{52.520529721073366}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419333457946777}, FloatLatitude{43.73708084564945}});
FloatCoordinate{FloatLongitude{13.407869338989258}, FloatLatitude{52.52144366674759}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.419043779373169}, FloatLatitude{43.737158363571325}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418915033340454}, FloatLatitude{43.737305647346446}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41848587989807}, FloatLatitude{43.7374916894919}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.418271303176879}, FloatLatitude{43.73746843425534}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417960166931152}, FloatLatitude{43.73744517900973}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417885065078735}, FloatLatitude{43.737212626056944}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417563199996948}, FloatLatitude{43.73703433484817}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4173057079315186}, FloatLatitude{43.73692580950463}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.417144775390625}, FloatLatitude{43.7367707729584}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416973114013672}, FloatLatitude{43.73653821738638}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416855096817017}, FloatLatitude{43.73639868360965}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.4167799949646}, FloatLatitude{43.736142870841206}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.41675853729248}, FloatLatitude{43.735848297208605}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416619062423706}, FloatLatitude{43.73567000193752}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416543960571288}, FloatLatitude{43.735406434042645}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416479587554932}, FloatLatitude{43.73529790574875}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416415214538574}, FloatLatitude{43.73515061703527}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416350841522218}, FloatLatitude{43.73490255101476}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416340112686156}, FloatLatitude{43.73475526132885}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416222095489501}, FloatLatitude{43.73446068087028}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416243553161621}, FloatLatitude{43.73430563794159}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.416050434112548}, FloatLatitude{43.73403431185051}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.415814399719239}, FloatLatitude{43.73382500231174}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.415750026702881}, FloatLatitude{43.73354592178871}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.415513992309569}, FloatLatitude{43.73347615145474}});
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.415342330932617}, FloatLatitude{43.733251335381205}});
FloatCoordinate{FloatLongitude{13.408942222595215}, FloatLatitude{52.52203119321206}});
TIMER_START(routes);
auto NUM = 100;

54
src/nodejs/CMakeLists.txt Normal file
View File

@ -0,0 +1,54 @@
# node-cmake requires CMake 3.1 features; for the osrm project we only
# require CMake 2.8.11 so that we can build e.g. on Trusty by default.
cmake_minimum_required(VERSION 3.1)
message(STATUS "Building node-osrm")
set(BINDING_DIR "${PROJECT_SOURCE_DIR}/lib/binding")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/nodejs")
include(FindNodeJS)
set(NodeJS_CXX_STANDARD 14 CACHE INTERNAL "Use C++14" FORCE)
set(NodeJS_DOWNLOAD ON CACHE INTERNAL "Download node.js sources" FORCE)
set(NodeJS_USE_CLANG_STDLIB OFF CACHE BOOL "Don't use libc++ by default" FORCE)
find_package(NodeJS REQUIRED)
add_nodejs_module(node-osrm node_osrm.cpp)
target_link_libraries(node-osrm osrm)
# node-osrm artifacts in ${BINDING_DIR} to depend targets on
set(ARTIFACTS "")
set(OSRM_BINARIES osrm-extract osrm-contract osrm-routed osrm-datastore osrm-components)
foreach(binary ${OSRM_BINARIES})
add_custom_command(OUTPUT ${BINDING_DIR}/${binary}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${binary}> ${BINDING_DIR}
DEPENDS ${binary} ${BINDING_DIR})
list(APPEND ARTIFACTS "${BINDING_DIR}/${binary}")
endforeach(binary)
# For mason-enabled builds we copy over tbb's shared objects for packaging.
# TODO: consider using statically linked tbb library (for node-osrm only!)
if (ENABLE_MASON)
foreach(libpath ${MASON_PACKAGE_tbb_LIBRARY_DIRS})
file(GLOB TBBGlob ${libpath}/*.*)
foreach(filepath ${TBBGlob})
get_filename_component(filename ${filepath} NAME)
add_custom_command(OUTPUT "${BINDING_DIR}/${filename}"
COMMAND ${CMAKE_COMMAND} -E copy ${filepath} ${BINDING_DIR}
DEPENDS ${filepath} ${BINDING_DIR})
list(APPEND ARTIFACTS "${BINDING_DIR}/${filename}")
endforeach()
endforeach()
endif()
add_custom_command(OUTPUT ${BINDING_DIR}/node-osrm.node
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:node-osrm> ${BINDING_DIR}
DEPENDS node-osrm ${BINDING_DIR})
list(APPEND ARTIFACTS "${BINDING_DIR}/node-osrm.node")
message(STATUS "node-osrm artifacts will be copied to: ${BINDING_DIR}")
add_custom_target(copy_artifacts ALL DEPENDS ${ARTIFACTS})

507
src/nodejs/node_osrm.cpp Normal file
View File

@ -0,0 +1,507 @@
#include "osrm/engine_config.hpp"
#include "osrm/osrm.hpp"
#include "osrm/match_parameters.hpp"
#include "osrm/nearest_parameters.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/table_parameters.hpp"
#include "osrm/tile_parameters.hpp"
#include "osrm/trip_parameters.hpp"
#include <exception>
#include <type_traits>
#include <utility>
#include "nodejs/node_osrm.hpp"
#include "nodejs/node_osrm_support.hpp"
namespace node_osrm
{
Engine::Engine(osrm::EngineConfig &config) : Base(), this_(std::make_shared<osrm::OSRM>(config)) {}
Nan::Persistent<v8::Function> &Engine::constructor()
{
static Nan::Persistent<v8::Function> init;
return init;
}
NAN_MODULE_INIT(Engine::Init)
{
const auto whoami = Nan::New("OSRM").ToLocalChecked();
auto fnTp = Nan::New<v8::FunctionTemplate>(New);
fnTp->InstanceTemplate()->SetInternalFieldCount(1);
fnTp->SetClassName(whoami);
SetPrototypeMethod(fnTp, "route", route);
SetPrototypeMethod(fnTp, "nearest", nearest);
SetPrototypeMethod(fnTp, "table", table);
SetPrototypeMethod(fnTp, "tile", tile);
SetPrototypeMethod(fnTp, "match", match);
SetPrototypeMethod(fnTp, "trip", trip);
const auto fn = Nan::GetFunction(fnTp).ToLocalChecked();
constructor().Reset(fn);
Nan::Set(target, whoami, fn);
}
/**
*
* The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance
* requires a `.osrm` network,
* which is prepared by the OSRM Backend C++ library. Once you have a complete `network.osrm` file,
* you can calculate
* networks in javascript with this library using the methods below. To create an OSRM instance with
* your network
* you need to construct an instance like this:
*
* ```javascript
* var osrm = new OSRM('network.osrm');
* ```
*
* #### Methods
*
* | Service | Description |
* |-----------------------------|-----------------------------------------------------------|
* | [`osrm.route`](#route) | shortest path between given coordinates |
* | [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
* | [`osrm.table`](#table) | computes distance tables for given coordinates |
* | [`osrm.match`](#match) | matches given coordinates to the road network |
* | [`osrm.trip`](#trip) | computes the shortest trip between given coordinates |
* | [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
*
* #### General Options
*
* Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options,
* outlined below.
*
* | Option | Values | Description
* | Format |
* | ----------- | ------------------------------------------------------- |
* ------------------------------------------------------------------------------------------------------
* | ------------------------------------------------------------------------------ |
* | coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this
* request will use. | `array` with
* `[{lon},{lat}]` values, in decimal degrees |
* | bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to
* segments with given bearing in degrees towards true north in clockwise direction. | `null` or
* `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
* | radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to
* given radius in meters. | `null` or
* `double >= 0` or `unlimited` (default) |
* | hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position
* in street network. | Base64 `string`
* |
*
* @class OSRM
*
*/
NAN_METHOD(Engine::New)
{
if (info.IsConstructCall())
{
try
{
auto config = argumentsToEngineConfig(info);
if (!config)
return;
auto *const self = new Engine(*config);
self->Wrap(info.This());
}
catch (const std::exception &ex)
{
return Nan::ThrowTypeError(ex.what());
}
info.GetReturnValue().Set(info.This());
}
else
{
return Nan::ThrowTypeError(
"Cannot call constructor as function, you need to use 'new' keyword");
}
}
template <typename ParameterParser, typename ServiceMemFn>
inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
ParameterParser argsToParams,
ServiceMemFn service,
bool requires_multiple_coordinates)
{
auto params = argsToParams(info, requires_multiple_coordinates);
if (!params)
return;
BOOST_ASSERT(params->IsValid());
if (!info[info.Length() - 1]->IsFunction())
return Nan::ThrowTypeError("last argument must be a callback function");
auto *const self = Nan::ObjectWrap::Unwrap<Engine>(info.Holder());
using ParamPtr = decltype(params);
struct Worker final : Nan::AsyncWorker
{
using Base = Nan::AsyncWorker;
Worker(std::shared_ptr<osrm::OSRM> osrm_,
ParamPtr params_,
ServiceMemFn service,
Nan::Callback *callback)
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
params{std::move(params_)}
{
}
void Execute() override try
{
const auto status = ((*osrm).*(service))(*params, result);
ParseResult(status, result);
}
catch (const std::exception &e)
{
SetErrorMessage(e.what());
}
void HandleOKCallback() override
{
Nan::HandleScope scope;
const constexpr auto argc = 2u;
v8::Local<v8::Value> argv[argc] = {Nan::Null(), render(result)};
callback->Call(argc, argv);
}
// Keeps the OSRM object alive even after shutdown until we're done with callback
std::shared_ptr<osrm::OSRM> osrm;
ServiceMemFn service;
const ParamPtr params;
// All services return json::Object .. except for Tile!
using ObjectOrString =
typename std::conditional<std::is_same<ParamPtr, tile_parameters_ptr>::value,
std::string,
osrm::json::Object>::type;
ObjectOrString result;
};
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
Nan::AsyncQueueWorker(new Worker{self->this_, std::move(params), service, callback});
}
/**
* Returns the fastest route between two or more coordinates while visiting the waypoints in order.
*
* @name route
* @memberof OSRM
* @param {Object} options Object literal containing parameters for the route query.
* @param {Boolean} [options.alternatives=false] Search for alternative routes and return as well.
* *Please note that even if an alternative route is requested, a result cannot be guaranteed.*
* @param {Boolean} [options.steps=false] Return route steps for each route leg.
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`,
* `datasources`, `speed`.
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview
* and per step). Can also be `geojson`.
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
* according to highest zoom level it could be display on, or not at all (`false`).
* @param {Boolean} [options.continue_straight] Forces the route to keep going straight at waypoints
* and don't do a uturn even if it would be faster. Default value depends on the profile.
* `null`/`true`/`false`
* @param {Function} callback
*
* @returns {Object} An array of [Waypoint](#waypoint) objects representing all waypoints in order
* AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
*
* @example
* var osrm = new OSRM("berlin-latest.osrm");
* osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
* if(err) throw err;
* console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
* console.log(result.routes); // array of Route objects ordered by descending recommendation rank
* });
*/
NAN_METHOD(Engine::route) //
{
async(info, &argumentsToRouteParameter, &osrm::OSRM::Route, true);
}
/**
* Snaps a coordinate to the street network and returns the nearest n matches.
*
* Note: `coordinates` in the general options only supports a single `{longitude},{latitude}` entry.
*
* @name nearest
* @memberof OSRM
* @param {Object} options - Object literal containing parameters for the nearest query.
* @param {Number} [options.number=1] Number of nearest segments that should be returned.
* Must be an integer greater than or equal to `1`.
* @param {Function} callback
*
* @returns {Object} containing `waypoints`.
* **`waypoints`**: array of [`aypoint`](#waypoint) objects sorted by distance to the input
* coordinate.
* Each object has an additional `distance` property, which is the distance in meters to the
* supplied
* input coordinate.
*
* @example
* var osrm = new OSRM('network.osrm');
* var options = {
* coordinates: [[13.388860,52.517037]],
* number: 3,
* bearings: [[0,20]]
* };
* osrm.nearest(options, function(err, response) {
* console.log(response.waypoints); // array of Waypoint objects
* });
*/
NAN_METHOD(Engine::nearest) //
{
async(info, &argumentsToNearestParameter, &osrm::OSRM::Nearest, false);
}
/**
* Computes duration tables for the given locations. Allows for both symmetric and asymmetric
* tables.
*
* @name table
* @memberof OSRM
* @param {Object} options - Object literal containing parameters for the table query.
* @param {Array} [options.sources] An array of `index` elements (`0 <= integer < #coordinates`) to
* use
* location with given index as source. Default is to use all.
* @param {Array} [options.destinations] An array of `index` elements (`0 <= integer <
* #coordinates`) to use location with given index as destination. Default is to use all.
* @param {Function} callback
*
* @returns {Object} containing `durations`, `sources`, and `destinations`.
* **`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
* gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
* **`sources`**: array of [`aypoint`](#waypoint) objects describing all sources in order.
* **`destinations`**: array of [`aypoint`](#waypoint) objects describing all destinations in
* order.
*
* @example
* var osrm = new OSRM('network.osrm');
* var options = {
* coordinates: [
* [13.388860,52.517037],
* [13.397634,52.529407],
* [13.428555,52.523219]
* ]
* };
* osrm.table(options, function(err, response) {
* console.log(response.durations); // array of arrays, matrix in row-major order
* console.log(response.sources); // array of Waypoint objects
* console.log(response.destinations); // array of Waypoint objects
* });
*/
NAN_METHOD(Engine::table) //
{
async(info, &argumentsToTableParameter, &osrm::OSRM::Table, true);
}
/**
* This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
* vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
* be used to examine the routing graph. The tiles are generated directly from the data in-memory,
* so are in sync with actual routing results, and let you examine which roads are actually
* routable,
* and what weights they have applied.
*
* @name tile
* @memberof OSRM
* @param {Array} ZXY - an array consisting of `x`, `y`, and `z` values representing tile
* coordinates like
* [wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
* and are supported by vector tile viewers like [Mapbox GL
* JS](https://www.mapbox.com/mapbox-gl-js/api/.
* @param {Function} callback
*
* @returns {Buffer} contains a Protocol Buffer encoded vector tile.
*
* @example
* var osrm = new OSRM('network.osrm');
* osrm.tile([0, 0, 0], function(err, response) {
* if (err) throw err;
* fs.writeFileSync('./tile.vector.pbf', response); // write the buffer to a file
* });
*/
NAN_METHOD(Engine::tile)
{
async(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/});
}
/**
* Map matching matches given GPS points to the road network in the most plausible way.
* Please note the request might result multiple sub-traces. Large jumps in the timestamps
* (>60s) or improbable transitions lead to trace splits if a complete matching could
* not be found. The algorithm might not be able to match all points. Outliers are removed
* if they can not be matched successfully.
*
* @name match
* @memberof OSRM
* @param {Object} options - Object literal containing parameters for the match query.
* @param {Boolean} [options.steps=false] Return route steps for each route.
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`,
* `datasources`, `speed`.
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview
* and per step). Can also be `geojson`.
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
* according to highest zoom level it could be display on, or not at all (`false`).
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like
* timestamp).
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching.
* If applicable use GPS accuracy (`double >= 0`, default `5m`).
* @param {Function} callback
*
* @returns {Object} containing `tracepoints` and `matchings`.
* **`tracepoints`** Array of [`aypoint`](#waypoint) objects representing all points of the trace
* in order.
* If the trace point was ommited by map matching because it is an outlier, the entry will be null.
* Each
* `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
* [`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
* the waypoint inside the matched route.
* **`matchings`** is an array of [`Route`](#route) objects that
* assemble the trace. Each `Route` object has an additional `confidence` property, which is the
* confidence of
* the matching. float value between `0` and `1`. `1` is very confident that the matching is
* correct.
*
* @example
* var osrm = new OSRM('network.osrm');
* var options = {
* coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
* timestamps: [1424684612, 1424684616, 1424684620]
* };
* osrm.match(options, function(err, response) {
* if (err) throw err;
* console.log(response.tracepoints); // array of Waypoint objects
* console.log(response.matchings); // array of Route objects
* });
*
*/
NAN_METHOD(Engine::match) //
{
async(info, &argumentsToMatchParameter, &osrm::OSRM::Match, true);
}
/**
* The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
* (farthest-insertion algorithm) for 10 or * more waypoints and uses brute force for less than 10
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
* only an approximation.
* Note that all input coordinates have to be connected for the trip service to work.
*
* @name trip
* @memberof OSRM
* @param {Object} options - Object literal containing parameters for the trip query.
* @param {Boolean} [options.steps=false] Return route steps for each route.
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`,
* `datasources`, `speed`.
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview
* and per step). Can also be `geojson`.
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
* @param {Function} callback
* @param {Boolean} [options.roundtrip=true] Return route is a roundtrip.
* @param {String} [options.source=any] Return route starts at `any` or `first` coordinate.
* @param {String} [options.destination=any] Return route ends at `any` or `last` coordinate.
*
* @returns {Object} containing `waypoints` and `trips`.
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input
* order.
* Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of
* the
* sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
* **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
*
* @example
* var osrm = new OSRM('network.osrm');
* var options = {
* coordinates: [
* [13.36761474609375, 52.51663871100423],
* [13.374481201171875, 52.506191342034576]
* ]
* }
* osrm.trip(options, function(err, response) {
* if (err) throw err;
* console.log(response.waypoints); // array of Waypoint objects
* console.log(response.trips); // array of Route objects
* });
*/
NAN_METHOD(Engine::trip) //
{
async(info, &argumentsToTripParameter, &osrm::OSRM::Trip, true);
}
/**
* Responses
* @class Responses
*/
/**
* Represents a route through (potentially multiple) waypoints.
*
* @name Route
* @memberof Responses
*
* @param {documentation} exteral in
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
*
*/
/**
* Represents a route between two waypoints.
*
* @name RouteLeg
* @memberof Responses
*
* @param {documentation} exteral in
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
*
*/
/**
* A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a
* single way to the subsequent step.
*
* @name RouteStep
* @memberof Responses
*
* @param {documentation} exteral in
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
*
*/
/**
*
* @name StepManeuver
* @memberof Responses
*
* @param {documentation} exteral in
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
*
*/
/**
* Object used to describe waypoint on a route.
*
* @name Waypoint
* @memberof Responses
*
* @param {documentation} exteral in
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
*
*/
} // namespace node_osrm

View File

@ -1,4 +1,4 @@
DATA_NAME:=monaco
DATA_NAME:=berlin
DATA_URL:=https://s3.amazonaws.com/mapbox/osrm/testing/$(DATA_NAME).osm.pbf
DATA_POLY_URL:=https://s3.amazonaws.com/mapbox/osrm/testing/$(DATA_NAME).poly
OSRM_BUILD_DIR?=../../build

View File

@ -1,2 +1,2 @@
2b8dd9343d5e615afc9c67bcc7028a63 monaco.osm.pbf
b0788991ab3791d53c1c20b6281f81ad monaco.poly
54707104e9f411d1a3032c00fb1276c6 berlin.osm.pbf
031d988f23fc2a30371c9ef8d2a49bae berlin.poly

58
test/nodejs/index.js Normal file
View File

@ -0,0 +1,58 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('constructor: throws if new keyword is not used', function(assert) {
assert.plan(1);
assert.throws(function() { OSRM(); },
/Cannot call constructor as function, you need to use 'new' keyword/);
});
test('constructor: uses defaults with no parameter', function(assert) {
assert.plan(1);
var osrm = new OSRM();
assert.ok(osrm);
});
test('constructor: does not accept more than one parameter', function(assert) {
assert.plan(1);
assert.throws(function() { new OSRM({}, {}); },
/Only accepts one parameter/);
});
test('constructor: throws if necessary files do not exist', function(assert) {
assert.plan(1);
assert.throws(function() { new OSRM("missing.osrm"); },
/Invalid file paths/);
});
test('constructor: takes a shared memory argument', function(assert) {
assert.plan(1);
var osrm = new OSRM({path: berlin_path, shared_memory: false});
assert.ok(osrm);
});
test('constructor: throws if shared_memory==false with no path defined', function(assert) {
assert.plan(1);
assert.throws(function() { var osrm = new OSRM({shared_memory: false}); },
/Shared_memory must be enabled if no path is specified/);
});
test('constructor: throws if given a non-bool shared_memory option', function(assert) {
assert.plan(1);
assert.throws(function() { var osrm = new OSRM({path: berlin_path, shared_memory: "a"}); },
/Shared_memory option must be a boolean/);
});
test('constructor: throws if given a non-string/obj argument', function(assert) {
assert.plan(1);
assert.throws(function() { var osrm = new OSRM(true); },
/Parameter must be a path or options object/);
});
require('./route.js');
require('./trip.js');
require('./match.js');
require('./tile.js');
require('./table.js');
require('./nearest.js');

195
test/nodejs/match.js Normal file
View File

@ -0,0 +1,195 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('match: match in Berlin', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: [1424684612, 1424684616, 1424684620]
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings.every(function(m) {
return !!m.distance && !!m.duration && Array.isArray(m.legs) && !!m.geometry && m.confidence > 0;
}))
assert.equal(response.tracepoints.length, 3);
assert.ok(response.tracepoints.every(function(t) {
return !!t.hint && !isNaN(t.matchings_index) && !isNaN(t.waypoint_index) && !!t.name;
}));
});
});
test('match: match in Berlin without timestamps', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]]
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.tracepoints.length, 3);
assert.equal(response.matchings.length, 1);
});
});
test('match: match in Berlin without geometry compression', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
geometries: 'geojson'
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings[0].geometry instanceof Object);
assert.ok(Array.isArray(response.matchings[0].geometry.coordinates));
});
});
test('match: match in Berlin with geometry compression', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]]
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.equal('string', typeof response.matchings[0].geometry);
});
});
test('match: match in Berlin with speed annotations options', function(assert) {
assert.plan(12);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: [1424684612, 1424684616, 1424684620],
radiuses: [4.07, 4.07, 4.07],
steps: true,
annotations: ['speed'],
overview: 'false',
geometries: 'geojson'
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings[0].confidence > 0, 'has confidence');
assert.ok(response.matchings[0].legs.every((l) => {return l.steps.length > 0; }), 'every leg has steps');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation; }), 'every leg has annotations');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.speed; }), 'every leg has annotations for speed');
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.duration; }), 'has no annotations for duration')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.distance; }), 'has no annotations for distance')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.nodes; }), 'has no annotations for nodes')
assert.equal(undefined, response.matchings[0].geometry);
});
});
test('match: match in Berlin with several (duration, distance, nodes) annotations options', function(assert) {
assert.plan(12);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: [1424684612, 1424684616, 1424684620],
radiuses: [4.07, 4.07, 4.07],
steps: true,
annotations: ['duration','distance','nodes'],
overview: 'false',
geometries: 'geojson'
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings[0].confidence > 0, 'has confidence');
assert.ok(response.matchings[0].legs.every((l) => {return l.steps.length > 0; }), 'every leg has steps');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation; }), 'every leg has annotations');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.distance; }), 'every leg has annotations for distance');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.duration; }), 'every leg has annotations for durations');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.nodes; }), 'every leg has annotations for nodes');
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(response.matchings[0].legs.every((l) => {return l.annotation.speed; }), 'has no annotations for speed')
assert.equal(undefined, response.matchings[0].geometry);
});
});
test('match: match in Berlin with all options', function(assert) {
assert.plan(8);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: [1424684612, 1424684616, 1424684620],
radiuses: [4.07, 4.07, 4.07],
steps: true,
annotations: true,
overview: 'false',
geometries: 'geojson'
};
osrm.match(options, function(err, response) {
assert.ifError(err);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings[0].confidence > 0, 'has confidence');
assert.ok(response.matchings[0].legs.every((l) => {return l.steps.length > 0; }), 'every leg has steps');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation; }), 'every leg has annotations');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.distance; }), 'every leg has annotations for distance');
assert.ok(response.matchings[0].legs.every((l) => {return l.annotation.duration; }), 'every leg has annotations for durations');
assert.equal(undefined, response.matchings[0].geometry);
});
});
test('match: throws on missing arguments', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.match({}) },
/Two arguments required/);
});
test('match: throws on non-object arg', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.match(null, function(err, response) {}) },
/First arg must be an object/);
});
test('match: throws on invalid coordinates param', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: ''
};
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = [[13.393252,52.542648]];
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/At least two coordinates must be provided/);
options.coordinates = [13.393252,52.542648];
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = [[13.393252],[52.542648]];
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
});
test('match: throws on invalid timestamps param', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
timestamps: 'timestamps'
};
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Timestamps must be an array of integers \(or undefined\)/);
options.timestamps = ['invalid', 'timestamp', 'array'];
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Timestamps array items must be numbers/);
options.timestamps = [1424684612, 1424684616];
assert.throws(function() { osrm.match(options, function(err, response) {}) },
/Timestamp array must have the same size as the coordinates array/);
});

51
test/nodejs/nearest.js Normal file
View File

@ -0,0 +1,51 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('nearest', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
osrm.nearest({
coordinates: [[13.333086, 52.4224]]
}, function(err, result) {
assert.ifError(err);
assert.equal(result.waypoints.length, 1);
assert.equal(result.waypoints[0].location.length, 2);
assert.ok(result.waypoints[0].hasOwnProperty('name'));
});
});
test('nearest: can ask for multiple nearest pts', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
osrm.nearest({
coordinates: [[13.333086, 52.4224]],
number: 3
}, function(err, result) {
assert.ifError(err);
assert.equal(result.waypoints.length, 3);
});
});
test('nearest: throws on invalid args', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
var options = {};
assert.throws(function() { osrm.nearest(options); },
/Two arguments required/);
assert.throws(function() { osrm.nearest(null, function(err, res) {}); },
/First arg must be an object/);
options.coordinates = [52.4224];
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
/Coordinates must be an array of /);
options.coordinates = [[13.333086, 52.4224],[13.333086, 52.5224]];
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
/Exactly one coordinate pair must be provided/);
options.coordinates = [[13.333086, 52.4224]];
options.number = 3.14159;
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
/Number must be an integer greater than or equal to 1/);
options.number = 0;
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
/Number must be an integer greater than or equal to 1/);
});

View File

@ -0,0 +1,8 @@
var path = require('path');
if (process.env.OSRM_DATA_PATH !== undefined) {
exports.data_path = path.join(path.resolve(process.env.OSRM_DATA_PATH), "berlin_CH.osrm");
console.log('Setting custom data path to ' + exports.data_path);
} else {
exports.data_path = path.resolve(path.join(__dirname, "../data/berlin_CH.osrm"));
}

471
test/nodejs/route.js Normal file
View File

@ -0,0 +1,471 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('route: routes Berlin', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, function(err, route) {
assert.ifError(err);
assert.ok(route.waypoints);
assert.ok(route.routes);
assert.ok(route.routes.length);
assert.ok(route.routes[0].geometry);
});
});
test('route: throws with too few or invalid args', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}) },
/Two arguments required/);
assert.throws(function() { osrm.route(null, function(err, route) {}) },
/First arg must be an object/);
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, true)},
/last argument must be a callback function/);
});
test('route: provides no alternatives by default, but when requested', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
var options = {coordinates: [[13.302383,52.490516], [13.418427,52.522070]]};
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.ok(route.routes);
assert.equal(route.routes.length, 1);
});
options.alternatives = true;
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.ok(route.routes);
assert.equal(route.routes.length, 2);
});
});
test('route: throws with bad params', function(assert) {
assert.plan(11);
var osrm = new OSRM(berlin_path);
assert.throws(function () { osrm.route({coordinates: []}, function(err) {}) });
assert.throws(function() { osrm.route({}, function(err, route) {}) },
/Must provide a coordinates property/);
assert.throws(function() { osrm.route({coordinates: null}, function(err, route) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.route({coordinates: [13.438640, 52.519930]}, function(err, route) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.route({coordinates: [[true, '52.519930'], [13.438640, 52.519930]]}, function(err, route) {}) },
/Each member of a coordinate pair must be a number/);
assert.throws(function() { osrm.route({coordinates: [[213.43864,252.51993],[413.415852,552.513191]]}, function(err, route) {}) },
/Lng\/Lat coordinates must be within world bounds \(-180 < lng < 180, -90 < lat < 90\)/);
assert.throws(function() { osrm.route({coordinates: [[13.438640], [52.519930]]}, function(err, route) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]], hints: null}, function(err, route) {}) },
/Hints must be an array of strings\/null/);
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]], steps: null}, function(err, route) {}) });
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]], annotations: null}, function(err, route) {}) });
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
alternateRoute: false,
hints: [13.438640, 52.519930]
};
assert.throws(function() { osrm.route(options, function(err, route) {}) },
/Hint must be null or string/);
});
test('route: routes Berlin using shared memory', function(assert) {
assert.plan(2);
var osrm = new OSRM();
osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, function(err, route) {
assert.ifError(err);
assert.ok(Array.isArray(route.routes));
});
});
test('route: routes Berlin with geometry compression', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
};
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.equal('string', typeof route.routes[0].geometry);
});
});
test('route: routes Berlin without geometry compression', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
geometries: 'geojson'
};
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.ok(Array.isArray(route.routes));
assert.ok(Array.isArray(route.routes[0].geometry.coordinates));
assert.equal(route.routes[0].geometry.type, 'LineString');
});
});
test('Test polyline6 geometries option', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: false,
overview: 'false',
geometries: 'polyline6',
steps: true
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.routes);
assert.equal(first.routes.length, 1);
assert.notOk(first.routes[0].geometry);
assert.ok(first.routes[0].legs[0]);
assert.equal(typeof first.routes[0].legs[0].steps[0].geometry, 'string');
});
});
test('route: routes Berlin with speed annotations options', function(assert) {
assert.plan(17);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: false,
overview: 'false',
geometries: 'polyline',
steps: true,
annotations: ['speed']
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.routes);
assert.ok(first.routes[0].legs.every(function(l) { return Array.isArray(l.steps) && l.steps.length > 0; }));
assert.equal(first.routes.length, 1);
assert.notOk(first.routes[0].geometry);
assert.ok(first.routes[0].legs[0]);
assert.ok(first.routes[0].legs.every(l => { return l.steps.length > 0; }), 'every leg has steps');
assert.ok(first.routes[0].legs.every(l => { return l.annotation;}), 'every leg has annotations');
assert.ok(first.routes[0].legs.every(l => { return l.annotation.speed;}), 'every leg has annotations for speed');
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.duration; }), 'has no annotations for duration')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.distance; }), 'has no annotations for distance')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.nodes; }), 'has no annotations for nodes')
options.overview = 'full';
osrm.route(options, function(err, full) {
assert.ifError(err);
options.overview = 'simplified';
osrm.route(options, function(err, simplified) {
assert.ifError(err);
assert.notEqual(full.routes[0].geometry, simplified.routes[0].geometry);
});
});
});
});
test('route: routes Berlin with several (duration, distance, nodes) annotations options', function(assert) {
assert.plan(17);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: false,
overview: 'false',
geometries: 'polyline',
steps: true,
annotations: ['duration','distance','nodes']
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.routes);
assert.ok(first.routes[0].legs.every(function(l) { return Array.isArray(l.steps) && l.steps.length > 0; }));
assert.equal(first.routes.length, 1);
assert.notOk(first.routes[0].geometry);
assert.ok(first.routes[0].legs[0]);
assert.ok(first.routes[0].legs.every(l => { return l.steps.length > 0; }), 'every leg has steps');
assert.ok(first.routes[0].legs.every(l => { return l.annotation;}), 'every leg has annotations');
assert.ok(first.routes[0].legs.every(l => { return l.annotation.distance;}), 'every leg has annotations for distance');
assert.ok(first.routes[0].legs.every(l => { return l.annotation.duration;}), 'every leg has annotations for durations');
assert.ok(first.routes[0].legs.every(l => { return l.annotation.nodes;}), 'every leg has annotations for nodes');
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(first.routes[0].legs.every(l => { return l.annotation.speed; }), 'has no annotations for speed')
options.overview = 'full';
osrm.route(options, function(err, full) {
assert.ifError(err);
options.overview = 'simplified';
osrm.route(options, function(err, simplified) {
assert.ifError(err);
assert.notEqual(full.routes[0].geometry, simplified.routes[0].geometry);
});
});
});
});
test('route: routes Berlin with options', function(assert) {
assert.plan(11);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: false,
overview: 'false',
geometries: 'polyline',
steps: true,
annotations: true
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.routes);
assert.ok(first.routes[0].legs.every(function(l) { return Array.isArray(l.steps) && l.steps.length > 0; }));
assert.equal(first.routes.length, 1);
assert.notOk(first.routes[0].geometry);
assert.ok(first.routes[0].legs[0]);
assert.ok(first.routes[0].legs.every(l => { return l.steps.length > 0; }), 'every leg has steps');
assert.ok(first.routes[0].legs.every(l => { return l.annotation;}), 'every leg has annotations');
options.overview = 'full';
osrm.route(options, function(err, full) {
assert.ifError(err);
options.overview = 'simplified';
osrm.route(options, function(err, simplified) {
assert.ifError(err);
assert.notEqual(full.routes[0].geometry, simplified.routes[0].geometry);
});
});
});
});
test('route: routes Berlin with options', function(assert) {
assert.plan(11);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: false,
overview: 'false',
geometries: 'polyline',
steps: true,
annotations: true
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.routes);
assert.ok(first.routes[0].legs.every(function(l) { return Array.isArray(l.steps) && l.steps.length > 0; }));
assert.equal(first.routes.length, 1);
assert.notOk(first.routes[0].geometry);
assert.ok(first.routes[0].legs[0]);
assert.ok(first.routes[0].legs.every(l => { return l.steps.length > 0; }), 'every leg has steps');
assert.ok(first.routes[0].legs.every(l => { return l.annotation;}), 'every leg has annotations');
options.overview = 'full';
osrm.route(options, function(err, full) {
assert.ifError(err);
options.overview = 'simplified';
osrm.route(options, function(err, simplified) {
assert.ifError(err);
assert.notEqual(full.routes[0].geometry, simplified.routes[0].geometry);
});
});
});
});
test('route: invalid route options', function(assert) {
assert.plan(8);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
continue_straight: []
}, function(err, route) {}); },
/must be boolean/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
alternatives: []
}, function(err, route) {}); },
/must be boolean/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
geometries: true
}, function(err, route) {}); },
/Geometries must be a string: \[polyline, polyline6, geojson\]/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
overview: false
}, function(err, route) {}); },
/Overview must be a string: \[simplified, full, false\]/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
overview: false
}, function(err, route) {}); },
/Overview must be a string: \[simplified, full, false\]/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
overview: 'maybe'
}, function(err, route) {}); },
/'overview' param must be one of \[simplified, full, false\]/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
geometries: 'maybe'
}, function(err, route) {}); },
/'geometries' param must be one of \[polyline, polyline6, geojson\]/);
assert.throws(function() { osrm.route({
coordinates: [[NaN, -NaN],[Infinity, -Infinity]]
}, function(err, route) {}); },
/Lng\/Lat coordinates must be valid numbers/);
});
test('route: integer bearing values no longer supported', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [200, 250],
};
assert.throws(function() { osrm.route(options, function(err, route) {}); },
/Bearing must be an array of \[bearing, range\] or null/);
});
test('route: valid bearing values', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [[200, 180], [250, 180]],
};
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.ok(route.routes[0]);
});
options.bearings = [null, [360, 180]];
osrm.route(options, function(err, route) {
assert.ifError(err);
assert.ok(route.routes[0]);
});
});
test('route: invalid bearing values', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [[400, 180], [-250, 180]],
}, function(err, route) {}) },
/Bearing values need to be in range 0..360, 0..180/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [[200], [250, 180]],
}, function(err, route) {}) },
/Bearing must be an array of/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [[400, 109], [100, 720]],
}, function(err, route) {}) },
/Bearing values need to be in range 0..360, 0..180/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: 400,
}, function(err, route) {}) },
/Bearings must be an array of arrays of numbers/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [[100, 100]],
}, function(err, route) {}) },
/Bearings array must have the same length as coordinates array/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
bearings: [Infinity, Infinity],
}, function(err, route) {}) },
/Bearing must be an array of \[bearing, range\] or null/);
});
test('route: routes Berlin with hints', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
};
osrm.route(options, function(err, first) {
assert.ifError(err);
assert.ok(first.waypoints);
var hints = first.waypoints.map(function(wp) { return wp.hint; });
assert.ok(hints.every(function(h) { return typeof h === 'string'; }));
options.hints = hints;
osrm.route(options, function(err, second) {
assert.ifError(err);
assert.deepEqual(first, second);
});
});
});
test('route: routes Berlin with null hints', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
hints: [null, null]
};
osrm.route(options, function(err, route) {
assert.ifError(err);
});
});
test('route: throws on bad hints', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
hints: ['', '']
}, function(err, route) {})}, /Hint cannot be an empty string/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
hints: [null]
}, function(err, route) {})}, /Hints array must have the same length as coordinates array/);
});
test('route: routes Berlin with valid radius values', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
radiuses: [100, 100]
};
osrm.route(options, function(err, route) {
assert.ifError(err);
});
options.radiuses = [null, null];
osrm.route(options, function(err, route) {
assert.ifError(err);
});
options.radiuses = [100, null];
osrm.route(options, function(err, route) {
assert.ifError(err);
});
});
test('route: throws on bad radiuses', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
radiuses: [10, 10]
};
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
radiuses: 10
}, function(err, route) {}) },
/Radiuses must be an array of non-negative doubles or null/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
radiuses: ['magic', 'numbers']
}, function(err, route) {}) },
/Radius must be non-negative double or null/);
assert.throws(function() { osrm.route({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
radiuses: [10]
}, function(err, route) {}) },
/Radiuses array must have the same length as coordinates array/);
});

161
test/nodejs/table.js Normal file
View File

@ -0,0 +1,161 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('table: distance table in Berlin', function(assert) {
assert.plan(9);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
};
osrm.table(options, function(err, table) {
assert.ifError(err);
assert.ok(Array.isArray(table.durations), 'result must be an array');
var row_count = table.durations.length;
for (var i = 0; i < row_count; ++i) {
var column = table.durations[i];
var column_count = column.length;
assert.equal(row_count, column_count);
for (var j = 0; j < column_count; ++j) {
if (i == j) {
// check that diagonal is zero
assert.equal(0, column[j], 'diagonal must be zero');
} else {
// everything else is non-zero
assert.notEqual(0, column[j], 'other entries must be non-zero');
}
}
}
assert.equal(options.coordinates.length, row_count);
});
});
test('table: distance table in Berlin with sources/destinations', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
sources: [0],
destinations: [0,1]
};
osrm.table(options, function(err, table) {
assert.ifError(err);
assert.ok(Array.isArray(table.durations), 'result must be an array');
var row_count = table.durations.length;
for (var i = 0; i < row_count; ++i) {
var column = table.durations[i];
var column_count = column.length;
assert.equal(options.destinations.length, column_count);
for (var j = 0; j < column_count; ++j) {
if (i == j) {
// check that diagonal is zero
assert.equal(0, column[j], 'diagonal must be zero');
} else {
// everything else is non-zero
assert.notEqual(0, column[j], 'other entries must be non-zero');
}
}
}
assert.equal(options.sources.length, row_count);
});
});
test('table: throws on invalid arguments', function(assert) {
assert.plan(14);
var osrm = new OSRM(berlin_path);
var options = {};
assert.throws(function() { osrm.table(options); },
/Two arguments required/);
options.coordinates = null;
assert.throws(function() { osrm.table(options, function() {}); },
/Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = [[13.393252,52.542648]];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/At least two coordinates must be provided/);
options.coordinates = [13.393252,52.542648];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = [[13.393252],[52.542648]];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = [[13.393252,52.542648],[13.393252,52.542648]];
options.sources = true;
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Sources must be an array of indices \(or undefined\)/);
options.sources = [0, 4];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Source indices must be less than or equal to the number of coordinates/);
options.sources = [0.3, 1.1];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Source must be an integer/);
options.destinations = true;
delete options.sources;
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Destinations must be an array of indices \(or undefined\)/);
options.destinations = [0, 4];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Destination indices must be less than or equal to the number of coordinates/);
options.destinations = [0.3, 1.1];
assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Destination must be an integer/);
// does not throw: the following two have been changed in OSRM v5
options.sources = [0, 1];
delete options.destinations;
assert.doesNotThrow(function() { osrm.table(options, function(err, response) {}) },
/Both sources and destinations need to be specified/);
options.destinations = [0, 1];
assert.doesNotThrow(function() { osrm.table(options, function(err, response) {}) },
/You can either specify sources and destinations, or coordinates/);
assert.throws(function() { osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]], generate_hints: null}, function(err, route) {}) },
/generate_hints must be of type Boolean/);
});
test('table: throws on invalid arguments', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.table(null, function() {}); },
/First arg must be an object/);
});
test('table: distance table in Berlin with hints', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
generate_hints: true // true is default but be explicit here
};
osrm.table(options, function(err, table) {
console.log(table);
assert.ifError(err);
function assertHasHints(waypoint) {
assert.notStrictEqual(waypoint.hint, undefined);
}
table.sources.map(assertHasHints);
table.destinations.map(assertHasHints);
});
});
test('table: distance table in Berlin without hints', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
generate_hints: false // true is default
};
osrm.table(options, function(err, table) {
assert.ifError(err);
function assertHasNoHints(waypoint) {
assert.strictEqual(waypoint.hint, undefined);
}
table.sources.map(assertHasNoHints);
table.destinations.map(assertHasNoHints);
});
});

23
test/nodejs/tile.js Normal file
View File

@ -0,0 +1,23 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = "test/data/berlin-latest.osrm";
test.test('tile check size coarse', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
osrm.tile([17603, 10747, 15], function(err, result) {
assert.ifError(err);
assert.ok(result.length > 35000);
});
});
// FIXME the size of the tile that is returned depends on the architecture
// See issue #3343 in osrm-backend
test.skip('tile', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
osrm.tile([17603, 10747, 15], function(err, result) {
assert.ifError(err);
assert.equal(result.length, 35970);
});
});

333
test/nodejs/trip.js Normal file
View File

@ -0,0 +1,333 @@
var OSRM = require('../../');
var test = require('tape');
var berlin_path = require('./osrm-data-path').data_path;
test('trip: trip in Berlin', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
osrm.trip({coordinates: [[13.36761474609375,52.51663871100423],[13.374481201171875,52.506191342034576]]}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t].geometry);
}
});
});
test('trip: trip with many locations in Berlin', function(assert) {
assert.plan(4);
var osrm = new OSRM(berlin_path);
var opts = {coordinates: [[13.36761474609375,52.51663871100423],[13.374481201171875,52.506191342034576],[13.404693603515625,52.50535544522142],[13.388900756835938,52.50159371284434],[13.386840820312498,52.518727886767266],[13.4088134765625,52.528754547664185],[13.41156005859375,52.51705655410405],[13.420486450195312,52.512042174642346],[13.413619995117188,52.50368360390624],[13.36212158203125,52.504101570196205],[13.35113525390625,52.52248815280757],[13.36761474609375,52.53460237630516],[13.383407592773438,52.53710835019913],[13.392333984375,52.536690697815736],[13.42529296875,52.532931647583325],[13.399200439453125,52.52415927884915],[13.390960693359375,52.51956352925745],[13.375167846679688,52.533349335723294],[13.37860107421875,52.520399155853454],[13.355255126953125,52.52081696319122],[13.385467529296875,52.5143405029259],[13.398857116699219,52.513086884218325],[13.399200439453125,52.50744515744915],[13.409500122070312,52.49783165855699],[13.424949645996094,52.500339730516934],[13.440055847167969,52.50786308797268],[13.428382873535156,52.511624283857785],[13.437652587890625,52.50451953251202],[13.443145751953125,52.5199813445422],[13.431129455566406,52.52520370034151],[13.418426513671875,52.52896341209634],[13.429069519042969,52.517474393230245],[13.418083190917969,52.528127948407935],[13.405036926269531,52.52833681581998],[13.384437561035156,52.53084314728766],[13.374481201171875,52.53084314728766],[13.3978271484375,52.532305107923925],[13.418769836425781,52.526039219655445],[13.441085815429688,52.51642978796417],[13.448638916015625,52.51601193890388],[13.44623565673828,52.50535544522142],[13.430442810058594,52.502638670794546],[13.358688354492188,52.520190250694526],[13.358001708984375,52.531887409851336],[13.367271423339842,52.528545682238736],[13.387870788574219,52.52958999943304],[13.406410217285156,52.53961418106945],[13.399543762207031,52.50556442091497],[13.374824523925781,52.50389258754797],[13.386154174804688,52.51099744023003],[13.40229034423828,52.49657756892365]]
};
osrm.trip(opts, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t].geometry);
}
assert.equal(opts.coordinates.length, trip.waypoints.length);
var indexMap = trip.waypoints.map(function(wp, i) {
return [i, wp.waypoint_index];
});
assert.ok(!indexMap.every(function(tuple) { return tuple[0] === tuple[1]; }));
});
});
test('trip: throws with too few or invalid args', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
assert.throws(function() { osrm.trip({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}) },
/Two arguments required/);
assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
/First arg must be an object/);
});
test('trip: throws with bad params', function(assert) {
assert.plan(14);
var osrm = new OSRM(berlin_path);
assert.throws(function () { osrm.trip({coordinates: []}, function(err) {}) });
assert.throws(function() { osrm.trip({}, function(err, trip) {}) },
/Must provide a coordinates property/);
assert.throws(function() { osrm.trip({
coordinates: null
}, function(err, trip) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.trip({
coordinates: [13.438640, 52.519930]
}, function(err, trip) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.trip({
coordinates: [[13.438640], [52.519930]]
}, function(err, trip) {}) },
/Coordinates must be an array of \(lon\/lat\) pairs/);
assert.throws(function() { osrm.trip({
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
hints: null
}, function(err, trip) {}) },
/Hints must be an array of strings\/null/);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
printInstructions: false,
hints: [13.438640, 52.519930]
};
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/Hint must be null or string/);
options.hints = [null];
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/Hints array must have the same length as coordinates array/);
delete options.hints;
options.geometries = 'false';
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/'geometries' param must be one of \[polyline, polyline6, geojson\]/);
delete options.geometries;
options.source = false;
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/Source must be a string: \[any, first\]/);
options.source = 'false';
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/'source' param must be one of \[any, first\]/);
delete options.source;
options.destination = true;
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/Destination must be a string: \[any, last\]/);
options.destination = 'true';
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/'destination' param must be one of \[any, last\]/);
options.roundtrip = 'any';
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
/'roundtrip' param must be a boolean/);
});
test('trip: routes Berlin using shared memory', function(assert) {
assert.plan(2);
var osrm = new OSRM();
osrm.trip({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t].geometry);
}
});
});
test('trip: routes Berlin with hints', function(assert) {
assert.plan(5);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
steps: false
};
osrm.trip(options, function(err, first) {
assert.ifError(err);
for (t = 0; t < first.trips.length; t++) {
assert.ok(first.trips[t].geometry);
}
var hints = first.waypoints.map(function(wp) { return wp.hint; });
assert.ok(hints.every(function(h) { return typeof h === 'string'; }));
options.hints = hints;
osrm.trip(options, function(err, second) {
assert.ifError(err);
assert.deepEqual(first, second);
});
});
});
test('trip: trip through Berlin with geometry compression', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal('string', typeof trip.trips[t].geometry);
}
});
});
test('trip: trip through Berlin without geometry compression', function(assert) {
assert.plan(2);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
geometries: 'geojson'
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(Array.isArray(trip.trips[t].geometry.coordinates));
}
});
});
test('trip: trip through Berlin with speed annotations options', function(assert) {
assert.plan(12);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
steps: true,
annotations: ['speed'],
overview: 'false'
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
assert.equal(trip.trips.length, 1);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t]);
assert.ok(trip.trips[t].legs.every(function(l) { return l.steps.length > 0; }), 'every leg has steps')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation; }), 'every leg has annotations')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation.speed; }), 'every leg has annotations for speed')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.duration; }), 'has no annotations for duration')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.distance; }), 'has no annotations for distance')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.nodes; }), 'has no annotations for nodes')
assert.notOk(trip.trips[t].geometry);
}
});
});
test('trip: trip through Berlin with several (duration, distance, nodes) annotations options', function(assert) {
assert.plan(12);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
steps: true,
annotations: ['duration', 'distance', 'nodes'],
overview: 'false'
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
assert.equal(trip.trips.length, 1);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t]);
assert.ok(trip.trips[t].legs.every(function(l) { return l.steps.length > 0; }), 'every leg has steps')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation; }), 'every leg has annotations')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation.duration; }), 'every leg has annotations for duration')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation.distance; }), 'every leg has annotations for distance')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation.nodes; }), 'every leg has annotations for nodes')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.weight; }), 'has no annotations for weight')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.datasources; }), 'has no annotations for datasources')
assert.notOk(trip.trips[t].legs.every(function(l) { return l.annotation.speed; }), 'has no annotations for speed')
assert.notOk(trip.trips[t].geometry);
}
});
});
test('trip: trip through Berlin with options', function(assert) {
assert.plan(6);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
steps: true,
annotations: true,
overview: 'false'
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
assert.equal(trip.trips.length, 1);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t]);
assert.ok(trip.trips[t].legs.every(function(l) { return l.steps.length > 0; }), 'every leg has steps')
assert.ok(trip.trips[t].legs.every(function(l) { return l.annotation; }), 'every leg has annotations')
assert.notOk(trip.trips[t].geometry);
}
});
});
test('trip: routes Berlin with null hints', function(assert) {
assert.plan(1);
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
printInstructions: false,
hints: [null, null]
};
osrm.trip(options, function(err, second) {
assert.ifError(err);
});
});
test('trip: service combinations that are not implemented', function(assert) {
assert.plan(3);
var osrm = new OSRM(berlin_path);
// fixed start, non-roundtrip
var options = {
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
source: 'first',
roundtrip: false
};
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
// fixed start, fixed end, non-roundtrip
options.source = 'any';
options.destination = 'any';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
// fixed end, non-roundtrip
delete options.source;
options.destination = 'last';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
});
test('trip: fixed start and end combinations', function(assert) {
var osrm = new OSRM(berlin_path);
var options = {
coordinates: [[13.36761474609375,52.51663871100423],[13.374481201171875,52.506191342034576]],
source: 'first',
destination: 'last',
roundtrip: false,
geometries: 'geojson'
};
// fixed start and end, non-roundtrip
osrm.trip(options, function(err, fseTrip) {
assert.ifError(err);
assert.equal(206.8, fseTrip.trips[0].duration);
assert.equal(1, fseTrip.trips.length);
var coordinates = fseTrip.trips[0].geometry.coordinates;
assert.equal(15, coordinates.length);
assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
});
// variations of roundtrip
var roundtripChecks = function(options) {
osrm.trip(options, function(err, trip) {
assert.ifError(err);
assert.equal(1, trip.trips.length);
assert.equal(422, Math.round(trip.trips[0].duration));
var coordinates = trip.trips[0].geometry.coordinates;
assert.equal(29, coordinates.length);
assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
});
}
// roundtrip, source and destination not specified
roundtripChecks({coordinates: options.coordinates, geometries: options.geometries});
// roundtrip, fixed destination
options.roundtrip = true;
delete options.source;
roundtripChecks(options);
//roundtrip, fixed source
delete options.destination;
options.source = 'first';
roundtripChecks(options);
// roundtrip, non-fixed source, non-fixed destination
options.source = 'any';
options.destination = 'any';
roundtripChecks(options);
assert.end();
});

View File

@ -5,7 +5,7 @@
#include <vector>
// Somewhere in 2b8dd9343d5e615afc9c67bcc7028a63 Monaco
// Somewhere in d41d8cd98f00b204e9800998ecf8427e Berlin
// Convenience aliases
using Longitude = osrm::util::FloatLongitude;
@ -15,21 +15,21 @@ using Locations = std::vector<Location>;
inline Location get_dummy_location()
{
return {osrm::util::FloatLongitude{7.437069}, osrm::util::FloatLatitude{43.749249}};
return {osrm::util::FloatLongitude{13.388860}, osrm::util::FloatLatitude{52.517037}};
}
inline Locations get_locations_in_small_component()
{
return {{Longitude{7.438023}, Latitude{43.746465}},
{Longitude{7.439263}, Latitude{43.746543}},
{Longitude{7.438190}, Latitude{43.747560}}};
return {{Longitude{13.459765}, Latitude{52.543193}},
{Longitude{13.461455}, Latitude{52.542381}},
{Longitude{13.462940}, Latitude{52.541774}}};
}
inline Locations get_locations_in_big_component()
{
return {{Longitude{7.415800}, Latitude{43.734132}},
{Longitude{7.417710}, Latitude{43.736721}},
{Longitude{7.421315}, Latitude{43.738814}}};
return {{Longitude{13.442631}, Latitude{52.551110}},
{Longitude{13.441193}, Latitude{52.549506}},
{Longitude{13.439648}, Latitude{52.547705}}};
}
#endif

View File

@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_extract_with_invalid_config)
BOOST_AUTO_TEST_CASE(test_extract_with_valid_config)
{
osrm::ExtractorConfig config;
config.input_path = {OSRM_TEST_DATA_DIR "/monaco.osm.pbf"};
config.input_path = OSRM_TEST_DATA_DIR "/berlin.osm.pbf";
config.requested_num_threads = tbb::task_scheduler_init::default_num_threads();
BOOST_CHECK_NO_THROW(osrm::extract(config));
}

View File

@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(test_trip_limits)
using namespace osrm;
EngineConfig config;
config.storage_config = {OSRM_TEST_DATA_DIR "/monaco_CH.osrm"};
config.storage_config = {OSRM_TEST_DATA_DIR "/berlin_CH.osrm"};
config.use_shared_memory = false;
config.max_locations_trip = 2;
@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(test_route_limits)
using namespace osrm;
EngineConfig config;
config.storage_config = {OSRM_TEST_DATA_DIR "/monaco_CH.osrm"};
config.storage_config = {OSRM_TEST_DATA_DIR "/berlin_CH.osrm"};
config.use_shared_memory = false;
config.max_locations_viaroute = 2;
@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(test_table_limits)
using namespace osrm;
EngineConfig config;
config.storage_config = {OSRM_TEST_DATA_DIR "/monaco_CH.osrm"};
config.storage_config = {OSRM_TEST_DATA_DIR "/berlin_CH.osrm"};
config.use_shared_memory = false;
config.max_locations_distance_table = 2;
@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(test_match_limits)
using namespace osrm;
EngineConfig config;
config.storage_config = {OSRM_TEST_DATA_DIR "/monaco_CH.osrm"};
config.storage_config = {OSRM_TEST_DATA_DIR "/berlin_CH.osrm"};
config.use_shared_memory = false;
config.max_locations_map_matching = 2;
@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_limits)
using namespace osrm;
EngineConfig config;
config.storage_config = {OSRM_TEST_DATA_DIR "/monaco_CH.osrm"};
config.storage_config = {OSRM_TEST_DATA_DIR "/berlin_CH.osrm"};
config.use_shared_memory = false;
config.max_results_nearest = 2;

View File

@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_match)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
MatchParameters params;
params.coordinates.push_back(get_dummy_location());

View File

@ -16,7 +16,7 @@ BOOST_AUTO_TEST_SUITE(nearest)
BOOST_AUTO_TEST_CASE(test_nearest_response)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_response)
BOOST_AUTO_TEST_CASE(test_nearest_response_no_coordinates)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_response_no_coordinates)
BOOST_AUTO_TEST_CASE(test_nearest_response_multiple_coordinates)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(test_nearest_response_multiple_coordinates)
BOOST_AUTO_TEST_CASE(test_nearest_response_for_location_in_small_component)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;

View File

@ -14,7 +14,7 @@ BOOST_AUTO_TEST_CASE(test_ch)
using namespace osrm;
EngineConfig config;
config.use_shared_memory = false;
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
config.algorithm = EngineConfig::Algorithm::CH;
OSRM osrm{config};
}
@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(test_corech)
using namespace osrm;
EngineConfig config;
config.use_shared_memory = false;
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/monaco_CoreCH.osrm");
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/berlin_CoreCH.osrm");
config.algorithm = EngineConfig::Algorithm::CoreCH;
OSRM osrm{config};
}
@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(test_mld)
using namespace osrm;
EngineConfig config;
config.use_shared_memory = false;
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/monaco_MLD.osrm");
config.storage_config = storage::StorageConfig(OSRM_TEST_DATA_DIR "/berlin_MLD.osrm");
config.algorithm = EngineConfig::Algorithm::MLD;
OSRM osrm{config};
}

View File

@ -17,7 +17,7 @@ BOOST_AUTO_TEST_SUITE(route)
BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -25,44 +25,38 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
params.steps = true;
params.coordinates.push_back(get_dummy_location());
params.coordinates.push_back(get_dummy_location());
params.generate_hints = false;
json::Object result;
const auto rc = osrm.Route(params, result);
BOOST_CHECK(rc == Status::Ok);
// unset snapping dependent hint
for (auto &itr : result.values["waypoints"].get<json::Array>().values)
itr.get<json::Object>().values["hint"] = "";
const auto location = json::Array{{{7.437070}, {43.749248}}};
const auto location = json::Array{{{13.3888}, {52.517033}}};
json::Object reference{
{{"code", "Ok"},
{"waypoints",
json::Array{
{json::Object{
{{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}},
json::Object{
{{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}}}}},
json::Array{{json::Object{{{"name", "Friedrichstraße"}, {"location", location}}},
json::Object{{{"name", "Friedrichstraße"}, {"location", location}}}}}},
{"routes",
json::Array{{json::Object{
{{"distance", 0.},
{"duration", 0.},
{"weight", 0.},
{"weight_name", "routability"},
{"geometry", "yw_jGupkl@??"},
{"geometry", "mfp_I__vpA??"},
{"legs",
json::Array{{json::Object{
{{"distance", 0.},
{"duration", 0.},
{"weight", 0.},
{"summary", "Boulevard du Larvotto"},
{"summary", "Friedrichstraße"},
{"steps",
json::Array{{{json::Object{{{"duration", 0.},
{"distance", 0.},
{"weight", 0.},
{"geometry", "yw_jGupkl@??"},
{"name", "Boulevard du Larvotto"},
{"geometry", "mfp_I__vpA??"},
{"name", "Friedrichstraße"},
{"mode", "driving"},
{"maneuver",
json::Object{{
@ -81,8 +75,8 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
json::Object{{{"duration", 0.},
{"distance", 0.},
{"weight", 0.},
{"geometry", "yw_jGupkl@"},
{"name", "Boulevard du Larvotto"},
{"geometry", "mfp_I__vpA"},
{"name", "Friedrichstraße"},
{"mode", "driving"},
{"maneuver",
json::Object{{{"location", location},
@ -103,7 +97,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
BOOST_AUTO_TEST_CASE(test_route_same_coordinates)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -255,7 +249,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates)
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -290,7 +284,7 @@ BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component)
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -325,7 +319,7 @@ BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component)
BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -362,7 +356,7 @@ BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components)
BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -382,7 +376,7 @@ BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints)
BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;
@ -416,7 +410,7 @@ BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance)
BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property)
{
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
using namespace osrm;

View File

@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_one_dest_matrix)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
TableParameters params;
params.coordinates.push_back(get_dummy_location());
@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(test_table_three_coords_one_source_matrix)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
TableParameters params;
params.coordinates.push_back(get_dummy_location());
@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(test_table_three_coordinates_matrix)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
TableParameters params;
params.coordinates.push_back(get_dummy_location());

View File

@ -24,16 +24,17 @@ BOOST_AUTO_TEST_CASE(test_tile)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
// This tile should contain most of monaco
TileParameters params{17059, 11948, 15};
// Tile within Berlin dataset at Hackescher Markt (13.40294, 52.52330)
TileParameters params{140831, 85967, 18};
std::string result;
const auto rc = osrm.Tile(params, result);
BOOST_CHECK(rc == Status::Ok);
BOOST_CHECK(result.size() > 114000);
BOOST_CHECK_GT(result.size(), 1500);
BOOST_CHECK_LT(result.size(), 2500);
protozero::pbf_reader tile_message(result);
tile_message.next();
@ -208,22 +209,24 @@ BOOST_AUTO_TEST_CASE(test_tile)
}
BOOST_CHECK_EQUAL(number_of_turn_keys, 3);
BOOST_CHECK(number_of_turns_found > 700);
BOOST_CHECK_GT(number_of_turns_found, 10); // roughly ten turns in the tile
}
BOOST_AUTO_TEST_CASE(test_tile_turns)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
// Small tile where we can test all the values
TileParameters params{272953, 191177, 19};
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
// Tile within Berlin dataset at Hackescher Markt (13.40294, 52.52330)
TileParameters params{140831, 85967, 18};
std::string result;
const auto rc = osrm.Tile(params, result);
BOOST_CHECK(rc == Status::Ok);
BOOST_CHECK_GT(result.size(), 128);
BOOST_CHECK_GT(result.size(), 1500);
BOOST_CHECK_LT(result.size(), 2500);
protozero::pbf_reader tile_message(result);
tile_message.next();
@ -331,7 +334,7 @@ BOOST_AUTO_TEST_CASE(test_tile_turns)
}
std::sort(actual_turn_penalties.begin(), actual_turn_penalties.end());
const std::vector<float> expected_turn_penalties = {
0, 0, 0, 0, 0, 0, .1f, .1f, .3f, .4f, 1.2f, 1.9f, 5.3f, 5.5f, 5.8f, 7.1f, 7.2f, 7.2f};
0., 0., 0., 0., 0., 0., 0., 0., 0.1, 0.7, 5.2, 7.1, 7.4};
CHECK_EQUAL_RANGE(actual_turn_penalties, expected_turn_penalties);
// Verify the expected turn angles
@ -343,7 +346,7 @@ BOOST_AUTO_TEST_CASE(test_tile_turns)
}
std::sort(actual_turn_angles.begin(), actual_turn_angles.end());
const std::vector<std::int64_t> expected_turn_angles = {
-122, -120, -117, -65, -57, -30, -28, -3, -2, 2, 3, 28, 30, 57, 65, 117, 120, 122};
-142, -118, -49, -13, -4, -2, -2, 2, 4, 13, 34, 49, 118};
CHECK_EQUAL_RANGE(actual_turn_angles, expected_turn_angles);
// Verify the expected bearings
@ -355,7 +358,7 @@ BOOST_AUTO_TEST_CASE(test_tile_turns)
}
std::sort(actual_turn_bearings.begin(), actual_turn_bearings.end());
const std::vector<std::int64_t> expected_turn_bearings = {
49, 49, 107, 107, 169, 169, 171, 171, 229, 229, 257, 257, 286, 286, 349, 349, 352, 352};
75, 75, 124, 124, 128, 242, 242, 255, 304, 304, 306, 308, 308};
CHECK_EQUAL_RANGE(actual_turn_bearings, expected_turn_bearings);
}
@ -363,7 +366,7 @@ BOOST_AUTO_TEST_CASE(test_tile_speeds)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
// Small tile so we can test all the values
// TileParameters params{272953, 191177, 19};
@ -499,26 +502,7 @@ BOOST_AUTO_TEST_CASE(test_tile_speeds)
actual_names.push_back(string_vals[i]);
}
std::sort(actual_names.begin(), actual_names.end());
const std::vector<std::string> expected_names = {"Avenue du Carnier",
"Avenue du Carnier",
"Avenue du Carnier",
"Avenue du Carnier",
"Avenue du Carnier",
"Avenue du Maréchal Foch",
"Avenue du Maréchal Foch",
"Avenue du Maréchal Foch",
"Avenue du Maréchal Foch",
"Avenue du Maréchal Foch",
"Avenue du Maréchal Foch",
"Avenue du Professeur Langevin",
"Avenue du Professeur Langevin",
"Avenue du Professeur Langevin",
"Montée de la Crémaillère",
"Montée de la Crémaillère",
"Rue Jules Ferry",
"Rue Jules Ferry",
"Rue Professeur Calmette",
"Rue Professeur Calmette"};
const std::vector<std::string> expected_names = {};
BOOST_CHECK(actual_names == expected_names);
}

View File

@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_in_small_component)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_small_component();
TripParameters params;
@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_in_big_component)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_big_component();
TripParameters params;
@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(test_roundtrip_response_for_locations_across_components)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto small = get_locations_in_small_component();
const auto big = get_locations_in_big_component();
@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(test_tfse_1)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_small_component();
TripParameters params;
@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(test_tfse_2)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_big_component();
TripParameters params;
@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_big_component();
auto params = osrm::TripParameters();
@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters)
BOOST_AUTO_TEST_CASE(test_tfse_legal_parameters)
{
using namespace osrm;
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/monaco_CH.osrm");
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/berlin_CH.osrm");
const auto locations = get_locations_in_big_component();
json::Object result;
TripParameters params;