Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cd40b9e90 | |||
| 45df8568b6 | |||
| 0da041477b | |||
| 272ea9b92e | |||
| 571681d019 | |||
| 9b614c6057 | |||
| 721f319909 | |||
| a3621f3655 | |||
| 789311abd6 | |||
| 091a495632 | |||
| 16665aeb00 | |||
| d6e56c38d5 | |||
| 87874006c7 | |||
| 703588b684 | |||
| b21ee1b63b | |||
| 427437d49b | |||
| 01deefc3bc | |||
| 157ca9161f | |||
| 266e65e6d2 | |||
| 70b3962c35 | |||
| e568b600f0 | |||
| 273fd689ce | |||
| 0363d64722 | |||
| d200507424 | |||
| fc84f605af | |||
| 927dea37bb | |||
| de98ae57b7 | |||
| 614398ed6c | |||
| 2cd4ba9a0a | |||
| 57d3f71bf9 | |||
| 8f8df969a2 | |||
| e39dc3c464 | |||
| dbc6535221 | |||
| e262cac3e8 | |||
| 4ab3165ae3 | |||
| 7a1a209168 | |||
| ac6f07a744 | |||
| dac929f8df | |||
| ebd938a8fc | |||
| 5ba54a62d6 | |||
| 827a595b6c | |||
| c03f74d8b0 | |||
| f5393f44f7 | |||
| ad6e834992 | |||
| 3439b21177 | |||
| 730c809395 | |||
| 5a2da798c8 | |||
| c0e7f6e9f4 | |||
| ed83d3ed13 | |||
| aa1dff3fc4 | |||
| c1901e9689 | |||
| c6e6d9fa94 | |||
| 88eabb98b9 | |||
| 3dcc7132b6 | |||
| 379380abd8 | |||
| 497709da13 | |||
| b95a58591d | |||
| 5727b1387e | |||
| 221cd00b1a | |||
| cce4f6344c | |||
| a49c6f433b | |||
| ef308ac53a | |||
| 2fab696bb3 | |||
| 836a5066c2 | |||
| 69422cc4e7 | |||
| e9c0987e8a | |||
| bd9eb76a2d | |||
| 441eae9df2 |
+29
-9
@@ -7,14 +7,20 @@ git:
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
nodejs:
|
||||
- "4"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
ccache: true
|
||||
apt: true
|
||||
directories:
|
||||
@@ -22,6 +28,8 @@ cache:
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "hk+32aXXF5t1ApaM2Wjqooz3dx1si907L87WRMkO47WlpJmUUU/Ye+MJk9sViH8MdhOcceocVAmdYl5/WFWOIbDWNlBya9QvXDZyIu2KIre/0QyOCTZbrsif8paBXKIO5O/R4OTvIZ8rvWZsadBdmAT9GSbDhih6FzqXAEgeIYQ="
|
||||
- secure: "VE+cFkseFwW4jK6XwkP0yW3h4DixPJ8+Eb3yKcchGZ5iIJxlZ/8i1vKHYxadgPRwSYwPSB14tF70xj2OmiT2keGzZUfphmPXinBaLEhYk+Bde+GZZkoSl5ND109I/LcyNr0nG9dDgtV6pkvFchgchpyP9JnVOOS0+crEZlAz0RE="
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CASHER_TIME_OUT=599 # one second less than 10m to avoid 10m timeout error: https://github.com/Project-OSRM/osrm-backend/issues/2742
|
||||
@@ -138,11 +146,12 @@ before_install:
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||
sudo mdutil -i off /
|
||||
npm install -g yarn
|
||||
fi
|
||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
|
||||
- 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 --ignore-scripts
|
||||
- yarn 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 +182,16 @@ 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 -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF}
|
||||
- |
|
||||
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_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||
-DBUILD_TOOLS=ON \
|
||||
-DENABLE_CCACHE=ON
|
||||
- echo "travis_fold:start:MAKE"
|
||||
- make --jobs=${JOBS}
|
||||
- make tests --jobs=${JOBS}
|
||||
@@ -190,7 +208,8 @@ install:
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
- npm run build-api-docs
|
||||
# building docs only works with npm3+ not with yarn or npm2
|
||||
#- yarn run docs
|
||||
|
||||
script:
|
||||
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
|
||||
@@ -204,8 +223,12 @@ script:
|
||||
- ./unit_tests/util-tests
|
||||
- ./unit_tests/server-tests
|
||||
- ./unit_tests/partition-tests
|
||||
- |
|
||||
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
|
||||
npm run nodejs-tests
|
||||
fi
|
||||
- popd
|
||||
- npm test
|
||||
- yarn test
|
||||
|
||||
after_success:
|
||||
- |
|
||||
@@ -215,8 +238,5 @@ after_success:
|
||||
|
||||
- |
|
||||
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
|
||||
nvm install 4
|
||||
nvm use 4
|
||||
source ./scripts/travis/build.sh
|
||||
./scripts/travis/publish.sh
|
||||
fi
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
- Track preprocessing flag in the map matching plugin.
|
||||
|
||||
# 5.7.0
|
||||
- Changes from 5.6
|
||||
- NodeJs Bindings
|
||||
@@ -8,6 +10,8 @@
|
||||
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
||||
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
||||
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
||||
- Profiles
|
||||
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
||||
|
||||
# 5.6.3
|
||||
- Changes from 5.6.0
|
||||
|
||||
@@ -303,6 +303,8 @@ endif()
|
||||
if (ENABLE_SANITIZER)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
|
||||
@@ -41,19 +41,27 @@ The easiest and quickest way to setup your own routing engine backend is to use
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base the Docker images on Alpine Linux and make sure they are as lightweight as possible (around 10-15 MB).
|
||||
In the following, replace `X.Y.Z` with the current stable release version.
|
||||
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
|
||||
```
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend:vX.Y.Z osrm-routed /data/berlin-latest.osrm
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
|
||||
curl http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
```
|
||||
|
||||
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
|
||||
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
|
||||
### Building from Source
|
||||
|
||||
The following targets Ubuntu 16.04.
|
||||
|
||||
+9
-3
@@ -141,15 +141,21 @@ SET test_osm=%test_region%.osm.pbf
|
||||
IF NOT EXIST %test_osm% powershell Invoke-WebRequest https://s3.amazonaws.com/mapbox/osrm/testing/monaco.osm.pbf -OutFile %test_osm%
|
||||
%Configuration%\osrm-extract.exe -p ../profiles/car.lua %test_osm%
|
||||
MKDIR ch
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* ch\
|
||||
XCOPY %test_region%.osrm.* ch\
|
||||
XCOPY %test_region%.osrm ch\
|
||||
MKDIR corech
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* corech\
|
||||
XCOPY %test_region%.osrm.* corech\
|
||||
XCOPY %test_region%.osrm corech\
|
||||
MKDIR mld
|
||||
XCOPY %test_region%.osrm %test_region%.osrm.* mld\
|
||||
XCOPY %test_region%.osrm.* mld\
|
||||
XCOPY %test_region%.osrm mld\
|
||||
%Configuration%\osrm-contract.exe %test_region_ch%.osrm
|
||||
%Configuration%\osrm-contract.exe --core 0.8 %test_region_corech%.osrm
|
||||
%Configuration%\osrm-partition.exe %test_region_mld%.osrm
|
||||
%Configuration%\osrm-customize.exe %test_region_mld%.osrm
|
||||
XCOPY /Y ch\*.* ..\test\data\ch\
|
||||
XCOPY /Y corech\*.* ..\test\data\corech\
|
||||
XCOPY /Y mld\*.* ..\test\data\mld\
|
||||
unit_tests\%Configuration%\library-tests.exe
|
||||
|
||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "user for publishing to s3://mapbox-node-binary/osrm",
|
||||
"Resources": {
|
||||
"User": {
|
||||
"Type": "AWS::IAM::User",
|
||||
"Properties": {
|
||||
"Policies": [
|
||||
{
|
||||
"PolicyName": "list",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::mapbox-node-binary",
|
||||
"Condition": {
|
||||
"StringLike": {
|
||||
"s3:prefix": [
|
||||
"osrm/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"PolicyName": "publish",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:DeleteObject",
|
||||
"s3:GetObject",
|
||||
"s3:GetObjectAcl",
|
||||
"s3:PutObject",
|
||||
"s3:PutObjectAcl"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::mapbox-node-binary/osrm/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"AccessKey": {
|
||||
"Type": "AWS::IAM::AccessKey",
|
||||
"Properties": {
|
||||
"UserName": {
|
||||
"Ref": "User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"AccessKeyId": {
|
||||
"Value": {
|
||||
"Ref": "AccessKey"
|
||||
}
|
||||
},
|
||||
"SecretAccessKey": {
|
||||
"Value": {
|
||||
"Fn::GetAtt": [
|
||||
"AccessKey",
|
||||
"SecretAccessKey"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
var cf = require('@mapbox/cloudfriend');
|
||||
var package_json = require('../package.json')
|
||||
|
||||
module.exports = {
|
||||
AWSTemplateFormatVersion: '2010-09-09',
|
||||
Description: 'user for publishing to s3://mapbox-node-binary/' + package_json.name,
|
||||
Resources: {
|
||||
User: {
|
||||
Type: 'AWS::IAM::User',
|
||||
Properties: {
|
||||
Policies: [
|
||||
{
|
||||
PolicyName: 'list',
|
||||
PolicyDocument: {
|
||||
Statement: [
|
||||
{
|
||||
Action: ['s3:ListBucket'],
|
||||
Effect: 'Allow',
|
||||
Resource: 'arn:aws:s3:::mapbox-node-binary',
|
||||
Condition : {
|
||||
StringLike : {
|
||||
"s3:prefix": [ package_json.name + "/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
PolicyName: 'publish',
|
||||
PolicyDocument: {
|
||||
Statement: [
|
||||
{
|
||||
Action: ['s3:DeleteObject', 's3:GetObject', 's3:GetObjectAcl', 's3:PutObject', 's3:PutObjectAcl'],
|
||||
Effect: 'Allow',
|
||||
Resource: 'arn:aws:s3:::mapbox-node-binary/' + package_json.name + '/*'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
AccessKey: {
|
||||
Type: 'AWS::IAM::AccessKey',
|
||||
Properties: {
|
||||
UserName: cf.ref('User')
|
||||
}
|
||||
}
|
||||
},
|
||||
Outputs: {
|
||||
AccessKeyId: {
|
||||
Value: cf.ref('AccessKey')
|
||||
},
|
||||
SecretAccessKey: {
|
||||
Value: cf.getAtt('AccessKey', 'SecretAccessKey')
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
coverage:
|
||||
|
||||
ignore:
|
||||
- unit_tests/.*
|
||||
- third_party/.*
|
||||
|
||||
comment: off
|
||||
|
||||
+5
-3
@@ -279,6 +279,8 @@ In addition to the [general options](#general-options) the following options are
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||
|gaps |`split` (default), `ignore` |Allows the input track splitting based on huge timestamp gaps between points. |
|
||||
|tidy |`true`, `false` (default) |Allows the input track modification to obtain better matching quality for noisy tracks. |
|
||||
|
||||
|Parameter |Values |
|
||||
|------------|-----------------------------------|
|
||||
@@ -314,7 +316,7 @@ All other properties might be undefined.
|
||||
|
||||
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 fastest path. As TSP is NP-hard it only returns an approximation.
|
||||
Note that all input coordinates have to be connected for the trip service to work.
|
||||
Note that all input coordinates have to be connected for the trip service to work.
|
||||
|
||||
```endpoint
|
||||
GET /trip/v1/{profile}/{coordinates}?roundtrip={true|false}&source{any|first}&destination{any|last}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}'
|
||||
@@ -334,7 +336,7 @@ In addition to the [general options](#general-options) the following options are
|
||||
|
||||
**Fixing Start and End Points**
|
||||
|
||||
It is possible to explicitely set the start or end coordinate of the trip.
|
||||
It is possible to explicitely 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.
|
||||
@@ -344,7 +346,7 @@ Right now, the following combinations are possible:
|
||||
|
||||
| roundtrip | source | destination | supported |
|
||||
| :-- | :-- | :-- | :-- |
|
||||
| true | first | last | **yes** |
|
||||
| true | first | last | **yes** |
|
||||
| true | first | any | **yes** |
|
||||
| true | any | last | **yes** |
|
||||
| true | any | any | **yes** |
|
||||
|
||||
+80
-3
@@ -25,6 +25,19 @@ As you scroll down the file you'll see local variables, and then local functions
|
||||
|
||||
`way_function` and `node_function` are the important functions which are called when extracting OpenStreetMap data with `osrm-extract`.
|
||||
|
||||
The following global properties can be set in your profile:
|
||||
|
||||
Attribute | Type | Notes
|
||||
------------------------------|----------|----------------------------------------------------------------------------
|
||||
weight_name | String | Name used in output for the routing weight property (default 'duration')
|
||||
weight_precision | Unsigned | Decimal precision of edge weights (default 1)
|
||||
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance)
|
||||
use_turn_restrictions | Boolean | Are turn instructions followed?
|
||||
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed?
|
||||
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
|
||||
max_turn_weight | Float | Maximum turn penalty weight
|
||||
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that segment_function will be called for all segments
|
||||
|
||||
## way_function
|
||||
|
||||
Given an OpenStreetMap way, the way_function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
||||
@@ -33,15 +46,79 @@ All other calculations stem from that, including the returned timings in driving
|
||||
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
||||
|
||||
## Guidance
|
||||
The following attributes can be set on the result in way_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||
forward_speed | Float | Speed on this way in km/h
|
||||
backward_speed | Float | " "
|
||||
forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6)
|
||||
backward_rate | Float | " "
|
||||
forward_mode | Enum | Mode of travel (e.g. car, ferry). Defined in include/extractor/travel_mode.hpp
|
||||
backward_mode | Enum | " "
|
||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM turn:lanes value)
|
||||
turn_lanes_backward | String | " "
|
||||
forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route)
|
||||
backward_restricted | Boolean | " "
|
||||
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if false, prevents snapping the start point to this way)
|
||||
roundabout | Boolean | Is this part of a roundabout?
|
||||
circular | Boolean | Is this part of a non-roundabout circular junction?
|
||||
name | String | Name of the way
|
||||
ref | String | Road number
|
||||
pronunciation | String | Name pronunciation
|
||||
road_classification.motorway_class | Boolean | Guidance: way is a motorway
|
||||
road_classification.link_class | Boolean | Guidance: way is a slip/link road
|
||||
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in include/extractor/guidance/road_classification.hpp
|
||||
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
||||
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
||||
|
||||
### Guidance
|
||||
|
||||
The guidance parameters in profiles are currently a work in progress. They can and will change.
|
||||
Please be aware of this when using guidance configuration possibilities.
|
||||
|
||||
### Road Classification
|
||||
|
||||
Guidance uses road classes to decide on when/if to emit specific instructions and to discover which road is obvious when following a route.
|
||||
Classification uses three flags and a priority-category.
|
||||
The flags indicate whether a road is a motorway (required for on/off ramps), a link type (the ramps itself, if also a motorway) and whether a road may be omittted in considerations (is considered purely for connectivity).
|
||||
The priority-category influences the decision which road is considered the obvious choice and which roads can be seen as fork.
|
||||
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
|
||||
|
||||
## node_function
|
||||
|
||||
The following attributes can be set on the result in node_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------|---------|-------------------------------------------------------
|
||||
barrier | Boolean | Is it an impassable barrier?
|
||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in turn_function)?
|
||||
|
||||
## segment_function
|
||||
|
||||
The following attributes can be read and set on the result in segment_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
source.lon | Read | Float | Co-ordinates of segment start
|
||||
source.lat | Read | Float | " "
|
||||
target.lon | Read | Float | Co-ordinates of segment end
|
||||
target.lat | Read | Float | " "
|
||||
target.distance | Read | Float | Length of segment
|
||||
weight | Read/write | Float | Routing weight for this segment
|
||||
duration | Read/write | Float | Duration for this segment
|
||||
|
||||
## turn_function
|
||||
|
||||
The following attributes can be read and set on the result in turn_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
direction_modifier | Read | Enum | Geometry of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
turn_type | Read | Enum | Priority of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in way_function)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in way_function)
|
||||
angle | Read | Float | Angle of turn in degrees (0-360: 0=u-turn, 180=straight on)
|
||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||
|
||||
+13
-9
@@ -32,21 +32,25 @@ We may introduce forward-compatible changes: query parameters and response prope
|
||||
|
||||
- The `master` branch is for the bleeding edge development
|
||||
- We create and maintain release branches `x.y` to control the release flow
|
||||
- We create the release branch once we tagged the final version `x.y.0` version, RCs go on master
|
||||
- We create the release branch once we create release branches once we want to release the first RC
|
||||
- RCs go in the release branch, commits needs to be cherry-picked from master
|
||||
- No minor or major version will be released without a code-equal release candidates
|
||||
- For quality assurance, release candidates will be run on the demo server for 24 hours before releaseing the version proper
|
||||
- For quality assurance, release candidates need to be staged beforing tagging a final release
|
||||
- Patch versions may be released without a release candidate
|
||||
- We may backport fixes to older versions and release them as patch versions
|
||||
|
||||
## Releasing a version
|
||||
|
||||
1. Check out the appropriate release branch `x.y`
|
||||
2. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
|
||||
3. Make sure `CHANGELOG.md` is up to date.
|
||||
4. Make sure the OSRM version in `CMakeLists.txt` is up to date
|
||||
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
|
||||
6. Use `npm run build-api-docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
|
||||
6. Push tags and commits: `git push; git push --tags`
|
||||
8. Proceede with the `node-osrm` release as [outlined in the repository](https://github.com/Project-OSRM/node-osrm/blob/master/docs/releasing.md).
|
||||
2. Make sure `CHANGELOG.md` is up to date.
|
||||
3. Make sure the OSRM version in `CMakeLists.txt` is up to date
|
||||
4. Make sure the `package.json` is up to date.
|
||||
5. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
|
||||
6. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
|
||||
7. Use `npm run build-api-docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
|
||||
8. Push tags and commits: `git push; git push --tags`
|
||||
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
||||
10. Wait until the travis build has been completed and check if the node binaries were published by doing:
|
||||
`rm -rf node_modules && npm install` locally.
|
||||
11. For final releases run `npm publish` or `npm publish --tag next` for release candidates.
|
||||
|
||||
|
||||
@@ -79,3 +79,19 @@ Feature: Bike - Cycle tracks/lanes
|
||||
| residential | lane | yes | x | x |
|
||||
| footway | lane | yes | x | x |
|
||||
| cycleway | lane | yes | x | x |
|
||||
|
||||
Scenario: Bike - Cycleway on oneways, modes
|
||||
Then routability should be
|
||||
| highway | cycleway | oneway | forw | backw |
|
||||
| motorway | track | yes | cycling | |
|
||||
| residential | track | yes | cycling | pushing bike |
|
||||
| cycleway | track | yes | cycling | pushing bike |
|
||||
| footway | track | yes | pushing bike | pushing bike |
|
||||
|
||||
Scenario: Bike - Cycleway on oneways, speeds
|
||||
Then routability should be
|
||||
| highway | cycleway | oneway | forw | backw |
|
||||
| motorway | track | yes | 15 km/h | |
|
||||
| residential | track | yes | 15 km/h | 6 km/h |
|
||||
| cycleway | track | yes | 15 km/h | 6 km/h |
|
||||
| footway | track | yes | 6 km/h +-1 | 6 km/h +-1 |
|
||||
|
||||
@@ -10,11 +10,11 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Help, short
|
||||
@@ -26,11 +26,11 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit successfully
|
||||
|
||||
Scenario: osrm-partition - Help, long
|
||||
@@ -42,9 +42,9 @@ Feature: osrm-partition command line options: help
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--min-cell-size"
|
||||
And stdout should contain "--balance"
|
||||
And stdout should contain "--boundary"
|
||||
And stdout should contain "--optimizing-cuts"
|
||||
And stdout should contain "--small-component-size"
|
||||
And stdout should contain "--max-cell-sizes"
|
||||
And it should exit successfully
|
||||
|
||||
@@ -18,3 +18,15 @@ Feature: osrm-partition command line options: invalid options
|
||||
And stderr should contain "option"
|
||||
And stderr should contain "fly-me-to-the-moon"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Check invalid values
|
||||
When I try to run "osrm-partition --max-cell-sizes 4,6@4,16 fly-me-to-the-moon.osrm"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "is invalid"
|
||||
And it should exit with an error
|
||||
|
||||
Scenario: osrm-partition - Check non-descending order
|
||||
When I try to run "osrm-partition --max-cell-sizes 4,64,16 fly-me-to-the-moon.osrm"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "must be sorted in non-descending order"
|
||||
And it should exit with an error
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
Feature: osrm-extract with a profile containing raster source
|
||||
Scenario: osrm-extract on a valid profile
|
||||
Given the profile "rasterbot"
|
||||
And the node map
|
||||
"""
|
||||
a b
|
||||
"""
|
||||
And the node locations
|
||||
| node | lat | lon |
|
||||
| a | 0.1 | 0.1 |
|
||||
| b | 0.05 | 0.1 |
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
@@ -20,4 +20,6 @@ Feature: osrm-extract with a profile containing raster source
|
||||
And the data has been saved to disk
|
||||
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||
Then stdout should contain "source loader"
|
||||
Then stdout should contain "slope: 0.0899"
|
||||
Then stdout should contain "slope: -0.0899"
|
||||
And it should exit successfully
|
||||
|
||||
@@ -50,8 +50,9 @@ Feature: Raster - weights
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 8 km/h |
|
||||
| a | c | ad,dc,dc | 15 km/h |
|
||||
| b | c | bc,bc | 8 km/h |
|
||||
| b | a | ab,ab | 22 km/h |
|
||||
| a | c | ab,bc,bc | 12 km/h |
|
||||
| b | c | bc,bc | 22 km/h |
|
||||
| a | d | ad,ad | 15 km/h |
|
||||
| d | c | dc,dc | 15 km/h |
|
||||
| d | e | de,de | 10 km/h |
|
||||
|
||||
@@ -40,6 +40,84 @@ Feature: Basic Map Matching
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 1 62 63 | ab,cd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace splitting suppression
|
||||
Given the query options
|
||||
| gaps | ignore |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 1 62 63 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Clean case.
|
||||
Given a grid size of 100 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abcd | 0 10 20 30 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Dirty case by ts.
|
||||
Given a grid size of 100 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | matchings |
|
||||
| abacd | 0 10 12 20 30 | abcd |
|
||||
|
||||
Scenario: Testbot - Map matching with trace tidying. Dirty case by dist.
|
||||
Given a grid size of 8 meters
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a q b c d
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| aqbcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | matchings |
|
||||
| abcbd | abbd |
|
||||
|
||||
Scenario: Testbot - Map matching with core factor
|
||||
Given the contract extra arguments "--core 0.8"
|
||||
Given the node map
|
||||
|
||||
@@ -3,7 +3,7 @@ Feature: Multi level routing
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16,64"
|
||||
|
||||
Scenario: Testbot - Multi level routing check partition
|
||||
Given the node map
|
||||
@@ -31,7 +31,7 @@ Feature: Multi level routing
|
||||
| be | primary |
|
||||
|
||||
And the data has been extracted
|
||||
When I run "osrm-partition --min-cell-size 4 --small-component-size 1 {processed_file}"
|
||||
When I run "osrm-partition --max-cell-sizes 4,16 --small-component-size 1 {processed_file}"
|
||||
Then it should exit successfully
|
||||
And stdout should not contain "level 1 #cells 1 bit size 1"
|
||||
|
||||
@@ -57,7 +57,6 @@ Feature: Multi level routing
|
||||
| cm | primary |
|
||||
| hj | primary |
|
||||
| kp | primary |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
@@ -88,7 +87,6 @@ Feature: Multi level routing
|
||||
| dim | primary |
|
||||
| glr | primary |
|
||||
| ot | secondary |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
@@ -113,6 +111,7 @@ Feature: Multi level routing
|
||||
│ │
|
||||
l───k
|
||||
"""
|
||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16"
|
||||
And the ways
|
||||
| nodes | maxspeed |
|
||||
| abcda | 5 |
|
||||
@@ -124,7 +123,6 @@ Feature: Multi level routing
|
||||
| fi | 15 |
|
||||
| gi | 15 |
|
||||
| hf | 100 |
|
||||
And the partition extra arguments "--min-cell-size 4 --small-component-size 1"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <tbb/enumerable_thread_specific.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace osrm
|
||||
@@ -15,12 +16,22 @@ namespace customizer
|
||||
|
||||
class CellCustomizer
|
||||
{
|
||||
private:
|
||||
struct HeapData
|
||||
{
|
||||
bool from_clique;
|
||||
};
|
||||
|
||||
public:
|
||||
using Heap =
|
||||
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
|
||||
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
|
||||
|
||||
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
||||
|
||||
template <typename GraphT>
|
||||
void Customize(const GraphT &graph, partition::CellStorage &cells, LevelID level, CellID id)
|
||||
void Customize(
|
||||
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
|
||||
{
|
||||
auto cell = cells.GetCell(level, id);
|
||||
auto destinations = cell.GetDestinationNodes();
|
||||
@@ -29,8 +40,8 @@ class CellCustomizer
|
||||
for (auto source : cell.GetSourceNodes())
|
||||
{
|
||||
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
|
||||
Heap heap(graph.GetNumberOfNodes());
|
||||
heap.Insert(source, 0, {});
|
||||
heap.Clear();
|
||||
heap.Insert(source, 0, {false});
|
||||
|
||||
// explore search space
|
||||
while (!heap.Empty() && !destinations_set.empty())
|
||||
@@ -39,9 +50,9 @@ class CellCustomizer
|
||||
const EdgeWeight weight = heap.GetKey(node);
|
||||
|
||||
if (level == 1)
|
||||
RelaxNode<true>(graph, cells, heap, level, id, node, weight);
|
||||
RelaxNode<true>(graph, cells, heap, level, node, weight);
|
||||
else
|
||||
RelaxNode<false>(graph, cells, heap, level, id, node, weight);
|
||||
RelaxNode<false>(graph, cells, heap, level, node, weight);
|
||||
|
||||
destinations_set.erase(node);
|
||||
}
|
||||
@@ -60,58 +71,67 @@ class CellCustomizer
|
||||
|
||||
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
|
||||
{
|
||||
Heap heap_exemplar(graph.GetNumberOfNodes());
|
||||
HeapPtr heaps(heap_exemplar);
|
||||
|
||||
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
|
||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||
auto &heap = heaps.local();
|
||||
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
||||
{
|
||||
Customize(graph, cells, level, id);
|
||||
Customize(graph, heap, cells, level, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct HeapData
|
||||
{
|
||||
};
|
||||
using Heap = util::
|
||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
using HeapPtr = boost::thread_specific_ptr<Heap>;
|
||||
|
||||
template <bool first_level, typename GraphT>
|
||||
void RelaxNode(const GraphT &graph,
|
||||
const partition::CellStorage &cells,
|
||||
Heap &heap,
|
||||
LevelID level,
|
||||
CellID id,
|
||||
NodeID node,
|
||||
EdgeWeight weight) const
|
||||
{
|
||||
BOOST_ASSERT(heap.WasInserted(node));
|
||||
|
||||
if (!first_level)
|
||||
{
|
||||
// Relax sub-cell nodes
|
||||
auto subcell_id = partition.GetCell(level - 1, node);
|
||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||
// if we reaches this node from a clique arc we don't need to scan
|
||||
// the clique arcs again because of the triangle inequality
|
||||
//
|
||||
// d(parent, node) + d(node, v) >= d(parent, v)
|
||||
//
|
||||
// And if there is a path (parent, node, v) there must also be a
|
||||
// clique arc (parent, v) with d(parent, v).
|
||||
if (!heap.GetData(node).from_clique)
|
||||
{
|
||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||
// Relax sub-cell nodes
|
||||
auto subcell_id = partition.GetCell(level - 1, node);
|
||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||
{
|
||||
const NodeID to = *subcell_destination;
|
||||
const EdgeWeight to_weight = subcell_weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
heap.Insert(to, to_weight, {});
|
||||
const NodeID to = *subcell_destination;
|
||||
const EdgeWeight to_weight = subcell_weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
{
|
||||
heap.Insert(to, to_weight, {true});
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
heap.GetData(to).from_clique = true;
|
||||
}
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
}
|
||||
}
|
||||
|
||||
++subcell_destination;
|
||||
++subcell_destination;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,11 +147,12 @@ class CellCustomizer
|
||||
const EdgeWeight to_weight = data.weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
{
|
||||
heap.Insert(to, to_weight, {});
|
||||
heap.Insert(to, to_weight, {false});
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
heap.GetData(to).from_clique = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace osrm
|
||||
@@ -16,16 +18,17 @@ namespace customizer
|
||||
|
||||
using EdgeBasedGraphEdgeData = partition::EdgeBasedGraphEdgeData;
|
||||
|
||||
struct MultiLevelEdgeBasedGraph : public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>
|
||||
struct MultiLevelEdgeBasedGraph
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
|
||||
{
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>;
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
struct MultiLevelEdgeBasedGraphView
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
|
||||
{
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>;
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ENGINE_API_MATCH_HPP
|
||||
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
#include "engine/api/route_api.hpp"
|
||||
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
@@ -21,8 +22,10 @@ namespace api
|
||||
class MatchAPI final : public RouteAPI
|
||||
{
|
||||
public:
|
||||
MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters ¶meters_)
|
||||
: RouteAPI(facade_, parameters_), parameters(parameters_)
|
||||
MatchAPI(const datafacade::BaseDataFacade &facade_,
|
||||
const MatchParameters ¶meters_,
|
||||
const tidy::Result &tidy_result_)
|
||||
: RouteAPI(facade_, parameters_), parameters(parameters_), tidy_result(tidy_result_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -83,13 +86,20 @@ class MatchAPI final : public RouteAPI
|
||||
for (auto point_index : util::irange(
|
||||
0u, static_cast<unsigned>(sub_matchings[sub_matching_index].indices.size())))
|
||||
{
|
||||
trace_idx_to_matching_idx[sub_matchings[sub_matching_index].indices[point_index]] =
|
||||
trace_idx_to_matching_idx[tidy_result
|
||||
.tidied_to_original[sub_matchings[sub_matching_index]
|
||||
.indices[point_index]]] =
|
||||
MatchingIndex{sub_matching_index, point_index};
|
||||
}
|
||||
}
|
||||
|
||||
for (auto trace_index : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
if (tidy_result.can_be_removed[trace_index])
|
||||
{
|
||||
waypoints.values.push_back(util::json::Null());
|
||||
continue;
|
||||
}
|
||||
auto matching_index = trace_idx_to_matching_idx[trace_index];
|
||||
if (matching_index.NotMatched())
|
||||
{
|
||||
@@ -111,6 +121,7 @@ class MatchAPI final : public RouteAPI
|
||||
}
|
||||
|
||||
const MatchParameters ¶meters;
|
||||
const tidy::Result &tidy_result;
|
||||
};
|
||||
|
||||
} // ns api
|
||||
|
||||
@@ -50,23 +50,34 @@ namespace api
|
||||
*/
|
||||
struct MatchParameters : public RouteParameters
|
||||
{
|
||||
enum class GapsType
|
||||
{
|
||||
Split,
|
||||
Ignore
|
||||
};
|
||||
|
||||
MatchParameters()
|
||||
: RouteParameters(false,
|
||||
false,
|
||||
false,
|
||||
RouteParameters::GeometriesType::Polyline,
|
||||
RouteParameters::OverviewType::Simplified,
|
||||
{})
|
||||
{}),
|
||||
gaps(GapsType::Split), tidy(false)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
MatchParameters(std::vector<unsigned> timestamps_, Args... args_)
|
||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)}
|
||||
MatchParameters(std::vector<unsigned> timestamps_, GapsType gaps_, bool tidy_, Args... args_)
|
||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)},
|
||||
gaps(gaps_), tidy(tidy_)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<unsigned> timestamps;
|
||||
GapsType gaps;
|
||||
bool tidy;
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return RouteParameters::IsValid() &&
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
#ifndef COORDINATE_TIDY
|
||||
#define COORDINATE_TIDY
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace api
|
||||
{
|
||||
namespace tidy
|
||||
{
|
||||
|
||||
struct Thresholds
|
||||
{
|
||||
double distance_in_meters;
|
||||
std::int32_t duration_in_seconds;
|
||||
};
|
||||
|
||||
using Mask = boost::dynamic_bitset<>;
|
||||
using Mapping = std::vector<std::size_t>;
|
||||
|
||||
struct Result
|
||||
{
|
||||
// Tidied parameters
|
||||
MatchParameters parameters;
|
||||
// Masking the MatchParameter parallel arrays for items which should be removed.
|
||||
Mask can_be_removed;
|
||||
// Maps the MatchParameter's original items to items which should not be removed.
|
||||
Mapping tidied_to_original;
|
||||
};
|
||||
|
||||
inline Result keep_all(const MatchParameters ¶ms)
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
result.tidied_to_original.reserve(params.coordinates.size());
|
||||
for (std::size_t current = 0; current < params.coordinates.size(); ++current)
|
||||
{
|
||||
result.tidied_to_original.push_back(current);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
||||
|
||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||
{
|
||||
if (!result.can_be_removed[i])
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
if (!params.radiuses.empty())
|
||||
result.parameters.radiuses.push_back(params.radiuses[i]);
|
||||
|
||||
if (!params.bearings.empty())
|
||||
result.parameters.bearings.push_back(params.bearings[i]);
|
||||
|
||||
if (!params.timestamps.empty())
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
|
||||
result.tidied_to_original.push_back(0);
|
||||
std::size_t last_good = 0;
|
||||
|
||||
const auto uses_timestamps = !params.timestamps.empty();
|
||||
|
||||
Thresholds running{0., 0};
|
||||
|
||||
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
||||
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
|
||||
{
|
||||
const auto next = current + 1;
|
||||
|
||||
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
||||
params.coordinates[current], params.coordinates[next]);
|
||||
running.distance_in_meters += distance_delta;
|
||||
const auto over_distance = running.distance_in_meters >= cfg.distance_in_meters;
|
||||
|
||||
if (uses_timestamps)
|
||||
{
|
||||
auto duration_delta = params.timestamps[next] - params.timestamps[current];
|
||||
running.duration_in_seconds += duration_delta;
|
||||
const auto over_duration = running.duration_in_seconds >= cfg.duration_in_seconds;
|
||||
|
||||
if (over_distance && over_duration)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
else
|
||||
{
|
||||
result.can_be_removed.set(next, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (over_distance)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
else
|
||||
{
|
||||
result.can_be_removed.set(next, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
||||
|
||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||
{
|
||||
if (!result.can_be_removed[i])
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
if (!params.radiuses.empty())
|
||||
result.parameters.radiuses.push_back(params.radiuses[i]);
|
||||
|
||||
if (!params.bearings.empty())
|
||||
result.parameters.bearings.push_back(params.bearings[i]);
|
||||
|
||||
if (!params.timestamps.empty())
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(result.tidied_to_original.size() == result.parameters.coordinates.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // ns tidy
|
||||
} // ns api
|
||||
} // ns engine
|
||||
} // ns osrm
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/exception.hpp"
|
||||
#include "util/exception_utils.hpp"
|
||||
@@ -61,7 +62,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CH>
|
||||
{
|
||||
private:
|
||||
using QueryGraph = util::StaticGraph<EdgeData, true>;
|
||||
using QueryGraph = util::StaticGraph<EdgeData, storage::Ownership::View>;
|
||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||
|
||||
@@ -78,9 +79,9 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
||||
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
|
||||
|
||||
util::ShM<GraphNode, true>::vector node_list(
|
||||
util::vector_view<GraphNode> node_list(
|
||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
||||
util::ShM<GraphEdge, true>::vector edge_list(
|
||||
util::vector_view<GraphEdge> edge_list(
|
||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
||||
m_query_graph.reset(new QueryGraph(node_list, edge_list));
|
||||
}
|
||||
@@ -154,7 +155,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
|
||||
{
|
||||
private:
|
||||
util::ShM<bool, true>::vector m_is_core_node;
|
||||
util::vector_view<bool> m_is_core_node;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -163,7 +164,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
{
|
||||
auto core_marker_ptr =
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
|
||||
util::ShM<bool, true>::vector is_core_node(
|
||||
util::vector_view<bool> is_core_node(
|
||||
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
|
||||
m_is_core_node = std::move(is_core_node);
|
||||
}
|
||||
@@ -199,10 +200,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
private:
|
||||
using super = BaseDataFacade;
|
||||
using IndexBlock = util::RangeTable<16, true>::BlockT;
|
||||
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
|
||||
using RTreeLeaf = super::RTreeLeaf;
|
||||
using SharedRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
|
||||
util::StaticRTree<RTreeLeaf, util::vector_view<util::Coordinate>, storage::Ownership::View>;
|
||||
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
||||
using RTreeNode = SharedRTree::TreeNode;
|
||||
|
||||
@@ -211,28 +212,28 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
extractor::Datasources *m_datasources;
|
||||
|
||||
unsigned m_check_sum;
|
||||
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
|
||||
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
|
||||
util::ShM<GeometryID, true>::vector m_via_geometry_list;
|
||||
util::ShM<NameID, true>::vector m_name_ID_list;
|
||||
util::ShM<LaneDataID, true>::vector m_lane_data_id;
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
|
||||
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
|
||||
util::ShM<util::guidance::TurnBearing, true>::vector m_pre_turn_bearing;
|
||||
util::ShM<util::guidance::TurnBearing, true>::vector m_post_turn_bearing;
|
||||
util::vector_view<util::Coordinate> m_coordinate_list;
|
||||
util::PackedVector<OSMNodeID, storage::Ownership::View> m_osmnodeid_list;
|
||||
util::vector_view<GeometryID> m_via_geometry_list;
|
||||
util::vector_view<NameID> m_name_ID_list;
|
||||
util::vector_view<LaneDataID> m_lane_data_id;
|
||||
util::vector_view<extractor::guidance::TurnInstruction> m_turn_instruction_list;
|
||||
util::vector_view<extractor::TravelMode> m_travel_mode_list;
|
||||
util::vector_view<util::guidance::TurnBearing> m_pre_turn_bearing;
|
||||
util::vector_view<util::guidance::TurnBearing> m_post_turn_bearing;
|
||||
util::NameTable m_names_table;
|
||||
util::ShM<unsigned, true>::vector m_name_begin_indices;
|
||||
util::ShM<bool, true>::vector m_is_core_node;
|
||||
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
|
||||
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
|
||||
util::ShM<TurnPenalty, true>::vector m_turn_weight_penalties;
|
||||
util::ShM<TurnPenalty, true>::vector m_turn_duration_penalties;
|
||||
util::vector_view<unsigned> m_name_begin_indices;
|
||||
util::vector_view<bool> m_is_core_node;
|
||||
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
|
||||
util::vector_view<TurnPenalty> m_turn_weight_penalties;
|
||||
util::vector_view<TurnPenalty> m_turn_duration_penalties;
|
||||
extractor::SegmentDataView segment_data;
|
||||
|
||||
util::ShM<char, true>::vector m_datasource_name_data;
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
|
||||
util::ShM<util::guidance::LaneTupleIdPair, true>::vector m_lane_tupel_id_pairs;
|
||||
util::vector_view<char> m_datasource_name_data;
|
||||
util::vector_view<std::size_t> m_datasource_name_offsets;
|
||||
util::vector_view<std::size_t> m_datasource_name_lengths;
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> m_lane_tupel_id_pairs;
|
||||
|
||||
std::unique_ptr<SharedRTree> m_static_rtree;
|
||||
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
|
||||
@@ -240,17 +241,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
util::NameTable m_name_table;
|
||||
// bearing classes by node based node
|
||||
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
|
||||
util::vector_view<BearingClassID> m_bearing_class_id_table;
|
||||
// entry class IDs
|
||||
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
|
||||
util::vector_view<EntryClassID> m_entry_class_id_list;
|
||||
|
||||
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
||||
// available turns. Such a class id is stored with every edge.
|
||||
util::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
|
||||
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
|
||||
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
|
||||
// at an intersection
|
||||
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
|
||||
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
|
||||
std::shared_ptr<util::RangeTable<16, storage::Ownership::View>> m_bearing_ranges_table;
|
||||
util::vector_view<DiscreteBearing> m_bearing_values_table;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -326,52 +327,52 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
|
||||
memory_block, storage::DataLayout::TRAVEL_MODE);
|
||||
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
|
||||
util::vector_view<extractor::TravelMode> travel_mode_list(
|
||||
travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
m_travel_mode_list = std::move(travel_mode_list);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
data_layout.GetBlockPtr<LaneDataID>(memory_block, storage::DataLayout::LANE_DATA_ID);
|
||||
util::ShM<LaneDataID, true>::vector lane_data_id(
|
||||
util::vector_view<LaneDataID> lane_data_id(
|
||||
lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
||||
m_lane_data_id = std::move(lane_data_id);
|
||||
|
||||
const auto lane_tupel_id_pair_ptr =
|
||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
||||
util::ShM<util::guidance::LaneTupleIdPair, true>::vector lane_tupel_id_pair(
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
|
||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
||||
|
||||
const auto turn_instruction_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
memory_block, storage::DataLayout::TURN_INSTRUCTION);
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
|
||||
util::vector_view<extractor::guidance::TurnInstruction> turn_instruction_list(
|
||||
turn_instruction_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
m_turn_instruction_list = std::move(turn_instruction_list);
|
||||
|
||||
const auto name_id_list_ptr =
|
||||
data_layout.GetBlockPtr<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
|
||||
util::ShM<NameID, true>::vector name_id_list(
|
||||
util::vector_view<NameID> name_id_list(
|
||||
name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
|
||||
m_name_ID_list = std::move(name_id_list);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
data_layout.GetBlockPtr<EntryClassID>(memory_block, storage::DataLayout::ENTRY_CLASSID);
|
||||
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
|
||||
typename util::vector_view<EntryClassID> entry_class_id_list(
|
||||
entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||
m_entry_class_id_list = std::move(entry_class_id_list);
|
||||
|
||||
const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::PRE_TURN_BEARING);
|
||||
typename util::ShM<util::guidance::TurnBearing, true>::vector pre_turn_bearing(
|
||||
typename util::vector_view<util::guidance::TurnBearing> pre_turn_bearing(
|
||||
pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||
m_pre_turn_bearing = std::move(pre_turn_bearing);
|
||||
|
||||
const auto post_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::POST_TURN_BEARING);
|
||||
typename util::ShM<util::guidance::TurnBearing, true>::vector post_turn_bearing(
|
||||
typename util::vector_view<util::guidance::TurnBearing> post_turn_bearing(
|
||||
post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
m_post_turn_bearing = std::move(post_turn_bearing);
|
||||
}
|
||||
@@ -380,7 +381,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto via_geometry_list_ptr =
|
||||
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::ShM<GeometryID, true>::vector via_geometry_list(
|
||||
util::vector_view<GeometryID> via_geometry_list(
|
||||
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
m_via_geometry_list = std::move(via_geometry_list);
|
||||
}
|
||||
@@ -398,14 +399,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
|
||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
|
||||
util::ShM<std::uint32_t, true>::vector offsets(
|
||||
util::vector_view<std::uint32_t> offsets(
|
||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
|
||||
m_lane_description_offsets = std::move(offsets);
|
||||
|
||||
auto masks_ptr = data_layout.GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
|
||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
|
||||
|
||||
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> masks(
|
||||
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
|
||||
m_lane_description_masks = std::move(masks);
|
||||
}
|
||||
@@ -414,12 +415,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
|
||||
m_turn_weight_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||
m_turn_weight_penalties = util::vector_view<TurnPenalty>(
|
||||
turn_weight_penalties_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
|
||||
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
|
||||
m_turn_duration_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||
m_turn_duration_penalties = util::vector_view<TurnPenalty>(
|
||||
turn_duration_penalties_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
|
||||
}
|
||||
@@ -428,42 +429,42 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto geometries_index_ptr =
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
|
||||
util::ShM<unsigned, true>::vector geometry_begin_indices(
|
||||
util::vector_view<unsigned> geometry_begin_indices(
|
||||
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
|
||||
|
||||
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
|
||||
util::ShM<NodeID, true>::vector geometry_node_list(
|
||||
util::vector_view<NodeID> geometry_node_list(
|
||||
geometries_node_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
|
||||
|
||||
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_fwd_weight_list(
|
||||
util::vector_view<EdgeWeight> geometry_fwd_weight_list(
|
||||
geometries_fwd_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_rev_weight_list(
|
||||
util::vector_view<EdgeWeight> geometry_rev_weight_list(
|
||||
geometries_rev_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_fwd_duration_list(
|
||||
util::vector_view<EdgeWeight> geometry_fwd_duration_list(
|
||||
geometries_fwd_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
|
||||
|
||||
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_rev_duration_list(
|
||||
util::vector_view<EdgeWeight> geometry_rev_duration_list(
|
||||
geometries_rev_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
|
||||
|
||||
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
|
||||
memory_block, storage::DataLayout::DATASOURCES_LIST);
|
||||
util::ShM<DatasourceID, true>::vector datasources_list(
|
||||
util::vector_view<DatasourceID> datasources_list(
|
||||
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]);
|
||||
|
||||
segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices),
|
||||
@@ -482,13 +483,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
|
||||
memory_block, storage::DataLayout::BEARING_CLASSID);
|
||||
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
|
||||
typename util::vector_view<BearingClassID> bearing_class_id_table(
|
||||
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
|
||||
m_bearing_class_id_table = std::move(bearing_class_id_table);
|
||||
|
||||
auto bearing_class_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
|
||||
memory_block, storage::DataLayout::BEARING_VALUES);
|
||||
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
|
||||
typename util::vector_view<DiscreteBearing> bearing_class_table(
|
||||
bearing_class_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
|
||||
m_bearing_values_table = std::move(bearing_class_table);
|
||||
|
||||
@@ -496,17 +497,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
|
||||
auto blocks_ptr =
|
||||
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
|
||||
util::ShM<unsigned, true>::vector bearing_offsets(
|
||||
util::vector_view<unsigned> bearing_offsets(
|
||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
|
||||
util::ShM<IndexBlock, true>::vector bearing_blocks(
|
||||
util::vector_view<IndexBlock> bearing_blocks(
|
||||
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
|
||||
|
||||
m_bearing_ranges_table = std::make_unique<util::RangeTable<16, true>>(
|
||||
m_bearing_ranges_table = std::make_unique<util::RangeTable<16, storage::Ownership::View>>(
|
||||
bearing_offsets, bearing_blocks, static_cast<unsigned>(m_bearing_values_table.size()));
|
||||
|
||||
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
|
||||
memory_block, storage::DataLayout::ENTRY_CLASS);
|
||||
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
|
||||
typename util::vector_view<util::guidance::EntryClass> entry_class_table(
|
||||
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
|
||||
m_entry_class_table = std::move(entry_class_table);
|
||||
}
|
||||
@@ -929,15 +930,13 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
memory_block, storage::DataLayout::MLD_PARTITION);
|
||||
auto partition_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
|
||||
util::ShM<PartitionID, true>::vector partition(mld_partition_ptr,
|
||||
partition_entries_count);
|
||||
util::vector_view<PartitionID> partition(mld_partition_ptr, partition_entries_count);
|
||||
|
||||
auto mld_chilren_ptr = data_layout.GetBlockPtr<CellID>(
|
||||
memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
auto children_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
util::ShM<CellID, true>::vector cell_to_children(mld_chilren_ptr,
|
||||
children_entries_count);
|
||||
util::vector_view<CellID> cell_to_children(mld_chilren_ptr, children_entries_count);
|
||||
|
||||
mld_partition =
|
||||
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
||||
@@ -969,15 +968,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
auto cell_level_offsets_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
||||
|
||||
util::ShM<EdgeWeight, true>::vector weights(mld_cell_weights_ptr, weight_entries_count);
|
||||
util::ShM<NodeID, true>::vector source_boundary(mld_source_boundary_ptr,
|
||||
source_boundary_entries_count);
|
||||
util::ShM<NodeID, true>::vector destination_boundary(
|
||||
mld_destination_boundary_ptr, destination_boundary_entries_count);
|
||||
util::ShM<partition::CellStorageView::CellData, true>::vector cells(
|
||||
mld_cells_ptr, cells_entries_counts);
|
||||
util::ShM<std::uint64_t, true>::vector level_offsets(mld_cell_level_offsets_ptr,
|
||||
cell_level_offsets_entries_count);
|
||||
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
|
||||
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
|
||||
source_boundary_entries_count);
|
||||
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
|
||||
destination_boundary_entries_count);
|
||||
util::vector_view<partition::CellStorageView::CellData> cells(mld_cells_ptr,
|
||||
cells_entries_counts);
|
||||
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
|
||||
cell_level_offsets_entries_count);
|
||||
|
||||
mld_cell_storage = partition::CellStorageView{std::move(weights),
|
||||
std::move(source_boundary),
|
||||
@@ -997,11 +996,11 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
auto graph_node_to_offset_ptr = data_layout.GetBlockPtr<QueryGraph::EdgeOffset>(
|
||||
memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET);
|
||||
|
||||
util::ShM<GraphNode, true>::vector node_list(
|
||||
util::vector_view<GraphNode> node_list(
|
||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
|
||||
util::ShM<GraphEdge, true>::vector edge_list(
|
||||
util::vector_view<GraphEdge> edge_list(
|
||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
|
||||
util::ShM<QueryGraph::EdgeOffset, true>::vector node_to_offset(
|
||||
util::vector_view<QueryGraph::EdgeOffset> node_to_offset(
|
||||
graph_node_to_offset_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]);
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ class RoutingAlgorithmsInterface
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const = 0;
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const = 0;
|
||||
|
||||
virtual std::vector<routing_algorithms::TurnData>
|
||||
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
@@ -79,11 +80,12 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const final override;
|
||||
|
||||
routing_algorithms::SubMatchingList MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const final override;
|
||||
routing_algorithms::SubMatchingList
|
||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const final override;
|
||||
|
||||
std::vector<routing_algorithms::TurnData>
|
||||
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
@@ -163,10 +165,16 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision) const
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting) const
|
||||
{
|
||||
return routing_algorithms::mapMatching(
|
||||
heaps, facade, candidates_list, trace_coordinates, trace_timestamps, trace_gps_precision);
|
||||
return routing_algorithms::mapMatching(heaps,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
allow_splitting);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
@@ -207,7 +215,8 @@ inline routing_algorithms::SubMatchingList
|
||||
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
|
||||
const std::vector<util::Coordinate> &,
|
||||
const std::vector<unsigned> &,
|
||||
const std::vector<boost::optional<double>> &) const
|
||||
const std::vector<boost::optional<double>> &,
|
||||
const bool) const
|
||||
{
|
||||
throw util::exception("MapMatching is not implemented");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision);
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
@@ -36,7 +37,8 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision);
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,13 +62,6 @@ struct ExtractionWay
|
||||
forward_restricted = false;
|
||||
}
|
||||
|
||||
// These accessors exists because it's not possible to take the address of a bitfield,
|
||||
// and LUA therefore cannot read/write the mode attributes directly.
|
||||
void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
|
||||
TravelMode get_forward_mode() const { return forward_travel_mode; }
|
||||
void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
|
||||
TravelMode get_backward_mode() const { return backward_travel_mode; }
|
||||
|
||||
// wrappers to allow assigning nil (nullptr) to string values
|
||||
void SetName(const char *value) { detail::maybeSetString(name, value); }
|
||||
const char *GetName() const { return name.c_str(); }
|
||||
@@ -105,14 +98,14 @@ struct ExtractionWay
|
||||
std::string destinations;
|
||||
std::string turn_lanes_forward;
|
||||
std::string turn_lanes_backward;
|
||||
bool roundabout;
|
||||
bool circular;
|
||||
bool is_startpoint;
|
||||
bool backward_restricted;
|
||||
bool forward_restricted;
|
||||
guidance::RoadClassification road_classification;
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
guidance::RoadClassification road_classification;
|
||||
bool roundabout : 1;
|
||||
bool circular : 1;
|
||||
bool is_startpoint : 1;
|
||||
bool forward_restricted : 1;
|
||||
bool backward_restricted : 1;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ class ExtractorCallbacks
|
||||
guidance::LaneDescriptionMap lane_description_map;
|
||||
ExtractionContainers &external_memory;
|
||||
bool fallback_to_duration;
|
||||
bool force_split_edges;
|
||||
|
||||
public:
|
||||
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||
|
||||
@@ -87,6 +87,7 @@ struct ProfileProperties
|
||||
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
|
||||
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
||||
unsigned weight_precision = 1;
|
||||
bool force_split_edges = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
@@ -22,24 +24,24 @@ class CompressedEdgeContainer;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class SegmentDataContainerImpl;
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace io
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
template <bool UseShareMemory>
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
|
||||
friend CompressedEdgeContainer;
|
||||
|
||||
@@ -188,12 +190,11 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
auto GetNumberOfGeometries() const { return index.size() - 1; }
|
||||
auto GetNumberOfSegments() const { return fwd_weights.size(); }
|
||||
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
friend void
|
||||
io::read<UseShareMemory>(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
friend void
|
||||
io::write<UseShareMemory>(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
io::write<Ownership>(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
|
||||
private:
|
||||
Vector<std::uint32_t> index;
|
||||
@@ -206,8 +207,8 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
};
|
||||
}
|
||||
|
||||
using SegmentDataView = detail::SegmentDataContainerImpl<true>;
|
||||
using SegmentDataContainer = detail::SegmentDataContainerImpl<false>;
|
||||
using SegmentDataView = detail::SegmentDataContainerImpl<storage::Ownership::View>;
|
||||
using SegmentDataContainer = detail::SegmentDataContainerImpl<storage::Ownership::Container>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,11 +112,18 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
|
||||
auto params = Nan::To<v8::Object>(args[0]).ToLocalChecked();
|
||||
|
||||
auto path = params->Get(Nan::New("path").ToLocalChecked());
|
||||
if (path.IsEmpty())
|
||||
return engine_config_ptr();
|
||||
|
||||
auto shared_memory = params->Get(Nan::New("shared_memory").ToLocalChecked());
|
||||
if (shared_memory.IsEmpty())
|
||||
return engine_config_ptr();
|
||||
|
||||
if (!path->IsUndefined())
|
||||
{
|
||||
engine_config->storage_config =
|
||||
osrm::StorageConfig(*v8::String::Utf8Value(Nan::To<v8::String>(path).ToLocalChecked()));
|
||||
engine_config->use_shared_memory = false;
|
||||
}
|
||||
if (!shared_memory->IsUndefined())
|
||||
{
|
||||
@@ -138,6 +145,37 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
|
||||
return engine_config_ptr();
|
||||
}
|
||||
|
||||
auto algorithm = params->Get(Nan::New("algorithm").ToLocalChecked());
|
||||
if (algorithm.IsEmpty())
|
||||
return engine_config_ptr();
|
||||
|
||||
if (algorithm->IsString())
|
||||
{
|
||||
auto algorithm_str = Nan::To<v8::String>(algorithm).ToLocalChecked();
|
||||
if (*v8::String::Utf8Value(algorithm_str) == std::string("CH"))
|
||||
{
|
||||
engine_config->algorithm = osrm::EngineConfig::Algorithm::CH;
|
||||
}
|
||||
else if (*v8::String::Utf8Value(algorithm_str) == std::string("CoreCH"))
|
||||
{
|
||||
engine_config->algorithm = osrm::EngineConfig::Algorithm::CoreCH;
|
||||
}
|
||||
else if (*v8::String::Utf8Value(algorithm_str) == std::string("MLD"))
|
||||
{
|
||||
engine_config->algorithm = osrm::EngineConfig::Algorithm::MLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("algorithm option must be one of 'CH', 'CoreCH', or 'MLD'.");
|
||||
return engine_config_ptr();
|
||||
}
|
||||
}
|
||||
else if (!algorithm->IsUndefined())
|
||||
{
|
||||
Nan::ThrowError("algorithm option must be a string and one of 'CH', 'CoreCH', or 'MLD'.");
|
||||
return engine_config_ptr();
|
||||
}
|
||||
|
||||
return engine_config;
|
||||
}
|
||||
|
||||
@@ -151,6 +189,8 @@ parseCoordinateArray(const v8::Local<v8::Array> &coordinates_array)
|
||||
for (uint32_t i = 0; i < coordinates_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> coordinate = coordinates_array->Get(i);
|
||||
if (coordinate.IsEmpty())
|
||||
return resulting_coordinates;
|
||||
|
||||
if (!coordinate->IsArray())
|
||||
{
|
||||
@@ -218,6 +258,9 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
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.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (coordinates->IsUndefined())
|
||||
{
|
||||
Nan::ThrowError("Must provide a coordinates property");
|
||||
@@ -258,6 +301,8 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
if (obj->Has(Nan::New("bearings").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> bearings = obj->Get(Nan::New("bearings").ToLocalChecked());
|
||||
if (bearings.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!bearings->IsArray())
|
||||
{
|
||||
@@ -276,6 +321,8 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
for (uint32_t i = 0; i < bearings_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> bearing_raw = bearings_array->Get(i);
|
||||
if (bearing_raw.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (bearing_raw->IsNull())
|
||||
{
|
||||
@@ -320,6 +367,8 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
if (obj->Has(Nan::New("hints").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> hints = obj->Get(Nan::New("hints").ToLocalChecked());
|
||||
if (hints.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!hints->IsArray())
|
||||
{
|
||||
@@ -338,6 +387,9 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
for (uint32_t i = 0; i < hints_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> hint = hints_array->Get(i);
|
||||
if (hint.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (hint->IsString())
|
||||
{
|
||||
if (hint->ToString()->Length() == 0)
|
||||
@@ -364,6 +416,8 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
if (obj->Has(Nan::New("radiuses").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> radiuses = obj->Get(Nan::New("radiuses").ToLocalChecked());
|
||||
if (radiuses.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!radiuses->IsArray())
|
||||
{
|
||||
@@ -382,6 +436,9 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
for (uint32_t i = 0; i < radiuses_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> radius = radiuses_array->Get(i);
|
||||
if (radius.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (radius->IsNull())
|
||||
{
|
||||
params->radiuses.emplace_back();
|
||||
@@ -401,6 +458,8 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
if (obj->Has(Nan::New("generate_hints").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> generate_hints = obj->Get(Nan::New("generate_hints").ToLocalChecked());
|
||||
if (generate_hints.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!generate_hints->IsBoolean())
|
||||
{
|
||||
@@ -420,6 +479,9 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
|
||||
if (obj->Has(Nan::New("steps").ToLocalChecked()))
|
||||
{
|
||||
auto steps = obj->Get(Nan::New("steps").ToLocalChecked());
|
||||
if (steps.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (steps->IsBoolean())
|
||||
{
|
||||
params->steps = steps->BooleanValue();
|
||||
@@ -434,6 +496,9 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
|
||||
if (obj->Has(Nan::New("annotations").ToLocalChecked()))
|
||||
{
|
||||
auto annotations = obj->Get(Nan::New("annotations").ToLocalChecked());
|
||||
if (annotations.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (annotations->IsBoolean())
|
||||
{
|
||||
params->annotations = annotations->BooleanValue();
|
||||
@@ -494,6 +559,8 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
|
||||
if (obj->Has(Nan::New("geometries").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> geometries = obj->Get(Nan::New("geometries").ToLocalChecked());
|
||||
if (geometries.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!geometries->IsString())
|
||||
{
|
||||
@@ -526,6 +593,8 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
|
||||
if (obj->Has(Nan::New("overview").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> overview = obj->Get(Nan::New("overview").ToLocalChecked());
|
||||
if (overview.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!overview->IsString())
|
||||
{
|
||||
@@ -572,9 +641,13 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("continue_straight").ToLocalChecked()))
|
||||
{
|
||||
auto value = obj->Get(Nan::New("continue_straight").ToLocalChecked());
|
||||
if (value.IsEmpty())
|
||||
return route_parameters_ptr();
|
||||
|
||||
if (!value->IsBoolean() && !value->IsNull())
|
||||
{
|
||||
Nan::ThrowError("'continue_straight' parama must be boolean or null");
|
||||
return route_parameters_ptr();
|
||||
}
|
||||
if (value->IsBoolean())
|
||||
{
|
||||
@@ -585,9 +658,13 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("alternatives").ToLocalChecked()))
|
||||
{
|
||||
auto value = obj->Get(Nan::New("alternatives").ToLocalChecked());
|
||||
if (value.IsEmpty())
|
||||
return route_parameters_ptr();
|
||||
|
||||
if (!value->IsBoolean())
|
||||
{
|
||||
Nan::ThrowError("'alternatives' parama must be boolean");
|
||||
return route_parameters_ptr();
|
||||
}
|
||||
params->alternatives = value->BooleanValue();
|
||||
}
|
||||
@@ -629,6 +706,8 @@ argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool
|
||||
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.IsEmpty() || y.IsEmpty() || z.IsEmpty())
|
||||
return tile_parameters_ptr();
|
||||
|
||||
if (!x->IsUint32() && !x->IsUndefined())
|
||||
{
|
||||
@@ -669,6 +748,8 @@ argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
return nearest_parameters_ptr();
|
||||
|
||||
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
|
||||
if (obj.IsEmpty())
|
||||
return nearest_parameters_ptr();
|
||||
|
||||
if (obj->Has(Nan::New("number").ToLocalChecked()))
|
||||
{
|
||||
@@ -706,10 +787,14 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
return table_parameters_ptr();
|
||||
|
||||
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[0]).ToLocalChecked();
|
||||
if (obj.IsEmpty())
|
||||
return table_parameters_ptr();
|
||||
|
||||
if (obj->Has(Nan::New("sources").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> sources = obj->Get(Nan::New("sources").ToLocalChecked());
|
||||
if (sources.IsEmpty())
|
||||
return table_parameters_ptr();
|
||||
|
||||
if (!sources->IsArray())
|
||||
{
|
||||
@@ -721,6 +806,9 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
for (uint32_t i = 0; i < sources_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> source = sources_array->Get(i);
|
||||
if (source.IsEmpty())
|
||||
return table_parameters_ptr();
|
||||
|
||||
if (source->IsUint32())
|
||||
{
|
||||
size_t source_value = static_cast<size_t>(source->NumberValue());
|
||||
@@ -744,6 +832,8 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("destinations").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> destinations = obj->Get(Nan::New("destinations").ToLocalChecked());
|
||||
if (destinations.IsEmpty())
|
||||
return table_parameters_ptr();
|
||||
|
||||
if (!destinations->IsArray())
|
||||
{
|
||||
@@ -755,6 +845,9 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
for (uint32_t i = 0; i < destinations_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> destination = destinations_array->Get(i);
|
||||
if (destination.IsEmpty())
|
||||
return table_parameters_ptr();
|
||||
|
||||
if (destination->IsUint32())
|
||||
{
|
||||
size_t destination_value = static_cast<size_t>(destination->NumberValue());
|
||||
@@ -798,6 +891,9 @@ argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("roundtrip").ToLocalChecked()))
|
||||
{
|
||||
auto roundtrip = obj->Get(Nan::New("roundtrip").ToLocalChecked());
|
||||
if (roundtrip.IsEmpty())
|
||||
return trip_parameters_ptr();
|
||||
|
||||
if (roundtrip->IsBoolean())
|
||||
{
|
||||
params->roundtrip = roundtrip->BooleanValue();
|
||||
@@ -812,6 +908,8 @@ argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("source").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> source = obj->Get(Nan::New("source").ToLocalChecked());
|
||||
if (source.IsEmpty())
|
||||
return trip_parameters_ptr();
|
||||
|
||||
if (!source->IsString())
|
||||
{
|
||||
@@ -839,6 +937,8 @@ argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("destination").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> destination = obj->Get(Nan::New("destination").ToLocalChecked());
|
||||
if (destination.IsEmpty())
|
||||
return trip_parameters_ptr();
|
||||
|
||||
if (!destination->IsString())
|
||||
{
|
||||
@@ -880,6 +980,8 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
if (obj->Has(Nan::New("timestamps").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> timestamps = obj->Get(Nan::New("timestamps").ToLocalChecked());
|
||||
if (timestamps.IsEmpty())
|
||||
return match_parameters_ptr();
|
||||
|
||||
if (!timestamps->IsArray())
|
||||
{
|
||||
@@ -899,6 +1001,9 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
for (uint32_t i = 0; i < timestamps_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> timestamp = timestamps_array->Get(i);
|
||||
if (timestamp.IsEmpty())
|
||||
return match_parameters_ptr();
|
||||
|
||||
if (!timestamp->IsNumber())
|
||||
{
|
||||
Nan::ThrowError("Timestamps array items must be numbers");
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
@@ -26,24 +27,23 @@ namespace partition
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class CellStorageImpl;
|
||||
template <storage::Ownership Ownership> class CellStorageImpl;
|
||||
}
|
||||
using CellStorage = detail::CellStorageImpl<false>;
|
||||
using CellStorageView = detail::CellStorageImpl<true>;
|
||||
using CellStorage = detail::CellStorageImpl<storage::Ownership::Container>;
|
||||
using CellStorageView = detail::CellStorageImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
template <bool UseShareMemory>
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path, detail::CellStorageImpl<Ownership> &storage);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class CellStorageImpl
|
||||
template <storage::Ownership Ownership> class CellStorageImpl
|
||||
{
|
||||
public:
|
||||
using WeightOffset = std::uint32_t;
|
||||
@@ -65,7 +65,7 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
|
||||
// Implementation of the cell view. We need a template parameter here
|
||||
// because we need to derive a read-only and read-write view from this.
|
||||
@@ -185,7 +185,8 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
|
||||
CellStorageImpl() {}
|
||||
|
||||
template <typename GraphT, typename = std::enable_if<!UseShareMemory>>
|
||||
template <typename GraphT,
|
||||
typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
CellStorageImpl(const partition::MultiLevelPartition &partition, const GraphT &base_graph)
|
||||
{
|
||||
// pre-allocate storge for CellData so we can have random access to it by cell id
|
||||
@@ -314,7 +315,7 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
weights.resize(weight_offset + 1, INVALID_EDGE_WEIGHT);
|
||||
}
|
||||
|
||||
template <typename = std::enable_if<UseShareMemory>>
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::View>>
|
||||
CellStorageImpl(Vector<EdgeWeight> weights_,
|
||||
Vector<NodeID> source_boundary_,
|
||||
Vector<NodeID> destination_boundary_,
|
||||
@@ -339,7 +340,8 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
destination_boundary.empty() ? nullptr : destination_boundary.data()};
|
||||
}
|
||||
|
||||
template <typename = std::enable_if<!UseShareMemory>> Cell GetCell(LevelID level, CellID id)
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
Cell GetCell(LevelID level, CellID id)
|
||||
{
|
||||
const auto level_index = LevelIDToIndex(level);
|
||||
BOOST_ASSERT(level_index < level_to_cell_offset.size());
|
||||
@@ -350,10 +352,10 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
cells[cell_index], weights.data(), source_boundary.data(), destination_boundary.data()};
|
||||
}
|
||||
|
||||
friend void io::read<UseShareMemory>(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
friend void io::write<UseShareMemory>(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<Ownership> &storage);
|
||||
friend void io::write<Ownership>(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
|
||||
private:
|
||||
Vector<EdgeWeight> weights;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -15,9 +16,8 @@ namespace partition
|
||||
namespace io
|
||||
{
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
@@ -27,9 +27,9 @@ inline void read(const boost::filesystem::path &path,
|
||||
reader.DeserializeVector(graph.edge_to_level);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
@@ -14,24 +16,23 @@ namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory> class MultiLevelGraph;
|
||||
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
|
||||
|
||||
namespace io
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void write(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void write(const boost::filesystem::path &path, const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
||||
{
|
||||
private:
|
||||
using SuperT = util::StaticGraph<EdgeDataT, UseSharedMemory>;
|
||||
template <typename T> using Vector = typename util::ShM<T, UseSharedMemory>::vector;
|
||||
using SuperT = util::StaticGraph<EdgeDataT, Ownership>;
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
|
||||
public:
|
||||
// We limit each node to have 255 edges
|
||||
@@ -110,9 +111,17 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
// which can be smaller then the total number of nodes.
|
||||
// this will save memory in case we sort the border nodes first
|
||||
if (index >= node_to_edge_offset.size() - 1)
|
||||
return SuperT::BeginEdges(node);
|
||||
{
|
||||
// On level 0 all edges are border edges
|
||||
if (level == 0)
|
||||
return SuperT::BeginEdges(node);
|
||||
else
|
||||
return SuperT::EndEdges(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SuperT::BeginEdges(node) + node_to_edge_offset[index + level];
|
||||
}
|
||||
}
|
||||
|
||||
// We save the level as sentinel at the end
|
||||
@@ -181,12 +190,10 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
node_to_edge_offset.push_back(mlp.GetNumberOfLevels());
|
||||
}
|
||||
|
||||
friend void
|
||||
io::read<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
friend void
|
||||
io::write<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
friend void io::read<EdgeDataT, Ownership>(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void io::write<EdgeDataT, Ownership>(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
Vector<EdgeOffset> node_to_edge_offset;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -25,31 +26,30 @@ namespace partition
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl;
|
||||
template <storage::Ownership Ownership> class MultiLevelPartitionImpl;
|
||||
}
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<false>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<true>;
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<storage::Ownership::Container>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
void read(const boost::filesystem::path &file,
|
||||
detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
|
||||
template <bool UseShareMemory>
|
||||
template <storage::Ownership Ownership>
|
||||
void read(const boost::filesystem::path &file, detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
template <storage::Ownership Ownership>
|
||||
void write(const boost::filesystem::path &file,
|
||||
const detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
|
||||
const detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
// we will support at most 16 levels
|
||||
static const constexpr std::uint8_t MAX_NUM_LEVEL = 16;
|
||||
static const constexpr std::uint8_t NUM_PARTITION_BITS = sizeof(PartitionID) * CHAR_BIT;
|
||||
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
|
||||
public:
|
||||
// Contains all data necessary to describe the level hierarchy
|
||||
@@ -68,7 +68,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
// cell_sizes is index by level (starting at 0, the base graph).
|
||||
// However level 0 always needs to have cell size 1, since it is the
|
||||
// basegraph.
|
||||
template <typename = typename std::enable_if<!UseShareMemory>>
|
||||
template <typename = typename std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
MultiLevelPartitionImpl(const std::vector<std::vector<CellID>> &partitions,
|
||||
const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
: level_data(MakeLevelData(lidx_to_num_cells))
|
||||
@@ -76,7 +76,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
InitializePartitionIDs(partitions);
|
||||
}
|
||||
|
||||
template <typename = typename std::enable_if<UseShareMemory>>
|
||||
template <typename = typename std::enable_if<Ownership == storage::Ownership::View>>
|
||||
MultiLevelPartitionImpl(LevelData level_data,
|
||||
Vector<PartitionID> partition_,
|
||||
Vector<CellID> cell_to_children_)
|
||||
@@ -134,10 +134,10 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
return cell_to_children[offset + cell + 1];
|
||||
}
|
||||
|
||||
friend void io::read<UseShareMemory>(const boost::filesystem::path &file,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void io::write<UseShareMemory>(const boost::filesystem::path &file,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &file,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void io::write<Ownership>(const boost::filesystem::path &file,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
|
||||
private:
|
||||
auto MakeLevelData(const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
|
||||
@@ -13,7 +13,12 @@ namespace partition
|
||||
|
||||
struct PartitionConfig
|
||||
{
|
||||
PartitionConfig() : requested_num_threads(0) {}
|
||||
PartitionConfig()
|
||||
: requested_num_threads(0), balance(1.2), boundary_factor(0.25), num_optimizing_cuts(10),
|
||||
small_component_size(1000),
|
||||
max_cell_sizes{128, 128 * 32, 128 * 32 * 16, 128 * 32 * 16 * 32}
|
||||
{
|
||||
}
|
||||
|
||||
void UseDefaults()
|
||||
{
|
||||
@@ -49,11 +54,11 @@ struct PartitionConfig
|
||||
|
||||
unsigned requested_num_threads;
|
||||
|
||||
std::size_t minimum_cell_size;
|
||||
double balance;
|
||||
double boundary_factor;
|
||||
std::size_t num_optimizing_cuts;
|
||||
std::size_t small_component_size;
|
||||
std::vector<std::size_t> max_cell_sizes;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,13 +33,24 @@ struct MatchParametersGrammar final : public RouteParametersGrammar<Iterator, Si
|
||||
(qi::uint_ %
|
||||
';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1];
|
||||
|
||||
root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
|
||||
-('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&');
|
||||
gaps_type.add("split", engine::api::MatchParameters::GapsType::Split)(
|
||||
"ignore", engine::api::MatchParameters::GapsType::Ignore);
|
||||
|
||||
root_rule =
|
||||
BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
|
||||
-('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1) |
|
||||
(qi::lit("gaps=") >
|
||||
gaps_type[ph::bind(&engine::api::MatchParameters::gaps, qi::_r1) = qi::_1]) |
|
||||
(qi::lit("tidy=") >
|
||||
qi::bool_[ph::bind(&engine::api::MatchParameters::tidy, qi::_r1) = qi::_1])) %
|
||||
'&');
|
||||
}
|
||||
|
||||
private:
|
||||
qi::rule<Iterator, Signature> root_rule;
|
||||
qi::rule<Iterator, Signature> timestamps_rule;
|
||||
|
||||
qi::symbols<char, engine::api::MatchParameters::GapsType> gaps_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
@@ -151,7 +153,7 @@ class SharedMemory
|
||||
#else
|
||||
void WaitForDetach()
|
||||
{
|
||||
util::Log(logWARNING)
|
||||
util::Log(logDEBUG)
|
||||
<< "Shared memory support for non-Linux systems does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
@@ -245,8 +247,8 @@ class SharedMemory
|
||||
void WaitForDetach()
|
||||
{
|
||||
// FIXME this needs an implementation for Windows
|
||||
util::Log(logWARNING) << "Shared memory support for Windows does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
util::Log(logDEBUG) << "Shared memory support for Windows does not wait for clients to "
|
||||
"dettach. Going to sleep for 50ms.";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef SHARED_MEMORY_OWNERSHIP_HPP
|
||||
#define SHARED_MEMORY_OWNERSHIP_HPP
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
{
|
||||
|
||||
enum class Ownership
|
||||
{
|
||||
Container,
|
||||
View
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARED_MEMORY_OWNERSHIP_HPP
|
||||
@@ -16,6 +16,48 @@ namespace osrm
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename NodeID, typename Key> class GenerationArrayStorage
|
||||
{
|
||||
using GenerationCounter = std::uint16_t;
|
||||
|
||||
public:
|
||||
explicit GenerationArrayStorage(std::size_t size)
|
||||
: positions(size, 0), generation(1), generations(size, 0)
|
||||
{
|
||||
}
|
||||
|
||||
Key &operator[](NodeID node)
|
||||
{
|
||||
generation[node] = generation;
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
if (generations[node] < generation)
|
||||
{
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
generation++;
|
||||
// if generation overflows we end up at 0 again and need to clear the vector
|
||||
if (generation == 0)
|
||||
{
|
||||
generation = 1;
|
||||
std::fill(generations.begin(), generations.end(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GenerationCounter generation;
|
||||
std::vector<GenerationCounter> generations;
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class ArrayStorage
|
||||
{
|
||||
public:
|
||||
@@ -92,10 +134,6 @@ template <typename NodeID,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||
class BinaryHeap
|
||||
{
|
||||
private:
|
||||
BinaryHeap(const BinaryHeap &right);
|
||||
void operator=(const BinaryHeap &right);
|
||||
|
||||
public:
|
||||
using WeightType = Weight;
|
||||
using DataType = Data;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
@@ -20,7 +22,8 @@ namespace util
|
||||
* NOTE: this type is templated for future use, but will require a slight refactor to
|
||||
* configure BITSIZE and ELEMSIZE
|
||||
*/
|
||||
template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
template <typename T, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class PackedVector
|
||||
{
|
||||
static const constexpr std::size_t BITSIZE = 33;
|
||||
static const constexpr std::size_t ELEMSIZE = 64;
|
||||
@@ -120,20 +123,20 @@ template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
|
||||
std::size_t size() const { return num_elements; }
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void reserve(typename std::enable_if<!enabled, std::size_t>::type capacity)
|
||||
{
|
||||
vec.reserve(elements_to_blocks(capacity));
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void reset(typename std::enable_if<enabled, std::uint64_t>::type *ptr,
|
||||
typename std::enable_if<enabled, std::size_t>::type size)
|
||||
{
|
||||
vec.reset(ptr, size);
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void set_number_of_entries(typename std::enable_if<enabled, std::size_t>::type count)
|
||||
{
|
||||
num_elements = count;
|
||||
@@ -145,44 +148,44 @@ template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
}
|
||||
|
||||
private:
|
||||
typename util::ShM<std::uint64_t, UseSharedMemory>::vector vec;
|
||||
typename util::ShM<std::uint64_t, Ownership>::vector vec;
|
||||
|
||||
std::size_t num_elements = 0;
|
||||
|
||||
signed cursor = -1;
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void replace_last_elem(typename std::enable_if<enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec[cursor] = last_elem;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void replace_last_elem(typename std::enable_if<!enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec.back() = last_elem;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void add_last_elem(typename std::enable_if<enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec[cursor + 1] = last_elem;
|
||||
cursor++;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void add_last_elem(typename std::enable_if<!enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec.push_back(last_elem);
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
std::uint64_t vec_back(typename std::enable_if<enabled>::type * = nullptr)
|
||||
{
|
||||
return vec[cursor];
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
std::uint64_t vec_back(typename std::enable_if<!enabled>::type * = nullptr)
|
||||
{
|
||||
return vec.back();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define RANGE_TABLE_HPP
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
|
||||
@@ -18,13 +19,14 @@ namespace util
|
||||
* and otherwise the compiler gets confused.
|
||||
*/
|
||||
|
||||
template <unsigned BLOCK_SIZE = 16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||
template <unsigned BLOCK_SIZE = 16, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class RangeTable;
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table);
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table);
|
||||
|
||||
/**
|
||||
* Stores adjacent ranges in a compressed format.
|
||||
@@ -35,12 +37,12 @@ std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEM
|
||||
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||
*/
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
|
||||
{
|
||||
public:
|
||||
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||
using BlockContainerT = typename ShM<BlockT, Ownership>::vector;
|
||||
using OffsetContainerT = typename ShM<unsigned, Ownership>::vector;
|
||||
using RangeT = range<unsigned>;
|
||||
|
||||
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
||||
@@ -139,7 +141,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
sum_lengths = lengths_prefix_sum;
|
||||
}
|
||||
|
||||
void Write(osrm::storage::io::FileWriter &filewriter)
|
||||
void Write(storage::io::FileWriter &filewriter)
|
||||
{
|
||||
unsigned number_of_blocks = diff_blocks.size();
|
||||
|
||||
@@ -151,7 +153,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
filewriter.WriteFrom(diff_blocks.data(), number_of_blocks);
|
||||
}
|
||||
|
||||
void Read(osrm::storage::io::FileReader &filereader)
|
||||
void Read(storage::io::FileReader &filereader)
|
||||
{
|
||||
unsigned number_of_blocks = filereader.ReadElementCount32();
|
||||
// read total length
|
||||
@@ -212,9 +214,8 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
unsigned sum_lengths;
|
||||
};
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
const BlockT &block) const
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
unsigned RangeTable<BLOCK_SIZE, Ownership>::PrefixSumAtIndex(int index, const BlockT &block) const
|
||||
{
|
||||
// this loop looks inefficent, but a modern compiler
|
||||
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||
@@ -227,8 +228,8 @@ unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table)
|
||||
{
|
||||
// write number of block
|
||||
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||
@@ -243,8 +244,8 @@ std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHA
|
||||
return out;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table)
|
||||
{
|
||||
// read number of block
|
||||
unsigned number_of_blocks;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
@@ -52,7 +54,7 @@ class ShMemIterator
|
||||
DataT *m_value;
|
||||
};
|
||||
|
||||
template <typename DataT> class SharedMemoryWrapper
|
||||
template <typename DataT> class vector_view
|
||||
{
|
||||
private:
|
||||
DataT *m_ptr;
|
||||
@@ -64,9 +66,9 @@ template <typename DataT> class SharedMemoryWrapper
|
||||
using const_iterator = ShMemIterator<const DataT>;
|
||||
using reverse_iterator = boost::reverse_iterator<iterator>;
|
||||
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
vector_view() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
vector_view(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
void reset(DataT *ptr, std::size_t size)
|
||||
{
|
||||
@@ -126,20 +128,19 @@ template <typename DataT> class SharedMemoryWrapper
|
||||
|
||||
auto data() const { return m_ptr; }
|
||||
|
||||
template <typename T>
|
||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
||||
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
||||
};
|
||||
|
||||
template <> class SharedMemoryWrapper<bool>
|
||||
template <> class vector_view<bool>
|
||||
{
|
||||
private:
|
||||
unsigned *m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
vector_view() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
vector_view(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
bool at(const std::size_t index) const
|
||||
{
|
||||
@@ -161,22 +162,20 @@ template <> class SharedMemoryWrapper<bool>
|
||||
|
||||
bool operator[](const unsigned index) const { return at(index); }
|
||||
|
||||
template <typename T>
|
||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
||||
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
||||
};
|
||||
|
||||
// Both SharedMemoryWrapper<T> and the SharedMemoryWrapper<bool> specializations share this impl.
|
||||
template <typename DataT>
|
||||
void swap(SharedMemoryWrapper<DataT> &lhs, SharedMemoryWrapper<DataT> &rhs) noexcept
|
||||
// Both vector_view<T> and the vector_view<bool> specializations share this impl.
|
||||
template <typename DataT> void swap(vector_view<DataT> &lhs, vector_view<DataT> &rhs) noexcept
|
||||
{
|
||||
std::swap(lhs.m_ptr, rhs.m_ptr);
|
||||
std::swap(lhs.m_size, rhs.m_size);
|
||||
}
|
||||
|
||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||
template <typename DataT, storage::Ownership Ownership> struct ShM
|
||||
{
|
||||
using vector = typename std::conditional<UseSharedMemory,
|
||||
SharedMemoryWrapper<DataT>,
|
||||
using vector = typename std::conditional<Ownership == storage::Ownership::View,
|
||||
vector_view<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -97,7 +99,8 @@ EntryT edgeToEntry(const OtherEdge &from, std::false_type)
|
||||
|
||||
} // namespace static_graph_details
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
template <typename EdgeDataT, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class StaticGraph
|
||||
{
|
||||
public:
|
||||
using InputEdge = static_graph_details::SortableEdgeWithData<EdgeDataT>;
|
||||
@@ -122,8 +125,8 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
InitializeFromSortedEdgeRange(nodes, edges.begin(), edges.end());
|
||||
}
|
||||
|
||||
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array_,
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array_)
|
||||
StaticGraph(typename util::ShM<NodeArrayEntry, Ownership>::vector node_array_,
|
||||
typename util::ShM<EdgeArrayEntry, Ownership>::vector edge_array_)
|
||||
: node_array(std::move(node_array_)), edge_array(std::move(edge_array_))
|
||||
{
|
||||
BOOST_ASSERT(!node_array.empty());
|
||||
@@ -258,8 +261,8 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
NodeIterator number_of_nodes;
|
||||
EdgeIterator number_of_edges;
|
||||
|
||||
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||
typename ShM<NodeArrayEntry, Ownership>::vector node_array;
|
||||
typename ShM<EdgeArrayEntry, Ownership>::vector edge_array;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@@ -52,7 +54,7 @@ namespace util
|
||||
// are computed, this means the internal distance metric doesn not represent meters!
|
||||
template <class EdgeDataT,
|
||||
class CoordinateListT = std::vector<Coordinate>,
|
||||
bool UseSharedMemory = false,
|
||||
storage::Ownership Ownership = storage::Ownership::Container,
|
||||
std::uint32_t BRANCHING_FACTOR = 128,
|
||||
std::uint32_t LEAF_PAGE_SIZE = 4096>
|
||||
class StaticRTree
|
||||
@@ -152,12 +154,12 @@ class StaticRTree
|
||||
Coordinate fixed_projected_coordinate;
|
||||
};
|
||||
|
||||
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||
typename ShM<TreeNode, Ownership>::vector m_search_tree;
|
||||
const CoordinateListT &m_coordinate_list;
|
||||
|
||||
boost::iostreams::mapped_file_source m_leaves_region;
|
||||
// read-only view of leaves
|
||||
typename ShM<const LeafNode, true>::vector m_leaves;
|
||||
typename ShM<const LeafNode, storage::Ownership::View>::vector m_leaves;
|
||||
|
||||
public:
|
||||
StaticRTree(const StaticRTree &) = delete;
|
||||
|
||||
+25
-27
@@ -1,25 +1,12 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.7.0",
|
||||
"private": true,
|
||||
"version": "5.7.0-latest.4",
|
||||
"private": false,
|
||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||
"dependencies": {
|
||||
"chalk": "^1.1.3",
|
||||
"cucumber": "^1.2.1",
|
||||
"d3-queue": "^2.0.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"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"
|
||||
"node-pre-gyp": "^0.6.34"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
@@ -30,19 +17,17 @@
|
||||
"scripts": {
|
||||
"lint": "eslint -c ./.eslintrc features/step_definitions/ features/support/",
|
||||
"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",
|
||||
|
||||
"preinstall": "npm install node-pre-gyp",
|
||||
"install": "node-pre-gyp install --fallback-to-build=false"
|
||||
"clean": "rm -rf test/cache",
|
||||
"docs": "./scripts/build_api_docs.sh",
|
||||
"install": "node-pre-gyp install --fallback-to-build=false",
|
||||
"nodejs-tests": "make -C test/data && ./lib/binding/osrm-datastore test/data/ch/monaco.osrm && node test/nodejs/index.js | faucet"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Project-OSRM/osrm-backend.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"author": "Project OSRM Team",
|
||||
"license": "BSD 2-Clause",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Project-OSRM/osrm-backend/issues"
|
||||
},
|
||||
@@ -51,12 +36,25 @@
|
||||
"node": ">=4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"docbox": "^1.0.2",
|
||||
"docbox": "^1.0.5",
|
||||
"documentation": "^4.0.0-beta.18",
|
||||
"eslint": "^2.4.0",
|
||||
|
||||
"chalk": "^1.1.3",
|
||||
"cucumber": "^1.2.1",
|
||||
"d3-queue": "^2.0.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"aws-sdk": "~2.0.31",
|
||||
"tape": "^4.2.2"
|
||||
"tape": "^4.2.2",
|
||||
"faucet": "^0.0.1",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"xmlbuilder": "^4.2.1"
|
||||
},
|
||||
"bundleDependencies": [
|
||||
"node-pre-gyp"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"binary": {
|
||||
"module_name": "node-osrm",
|
||||
|
||||
+16
-4
@@ -444,17 +444,29 @@ function way_function (way, result)
|
||||
end
|
||||
|
||||
-- cycleways
|
||||
local has_cycleway_left, has_cycleway_right
|
||||
if cycleway and profile.cycleway_tags[cycleway] then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
elseif cycleway_left and profile.cycleway_tags[cycleway_left] then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
elseif cycleway_right and profile.cycleway_tags[cycleway_right] then
|
||||
has_cycleway_left = true
|
||||
has_cycleway_right = true
|
||||
end
|
||||
if has_cycleway_right and
|
||||
(result.forward_mode == mode.inaccessible or
|
||||
result.forward_mode == mode.cycling) then
|
||||
result.forward_speed = profile.bicycle_speeds["cycleway"]
|
||||
end
|
||||
if has_cycleway_left and
|
||||
(result.backward_mode == mode.inaccessible or
|
||||
result.backward_mode == mode.cycling) then
|
||||
result.backward_speed = profile.bicycle_speeds["cycleway"]
|
||||
end
|
||||
|
||||
|
||||
-- dismount
|
||||
if bicycle == "dismount" then
|
||||
result.forward_mode = mode.pushing_bike
|
||||
|
||||
@@ -33,6 +33,7 @@ local profile = {
|
||||
'sally_port',
|
||||
'gate',
|
||||
'no',
|
||||
'kerb',
|
||||
'block'
|
||||
},
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
api_version = 1
|
||||
-- Rasterbot profile
|
||||
|
||||
properties.force_split_edges = true
|
||||
|
||||
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
||||
|
||||
function node_function (node, result)
|
||||
@@ -46,7 +48,7 @@ function segment_function (segment)
|
||||
local scaled_duration = segment.duration
|
||||
|
||||
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||
local slope = math.abs(sourceData.datum - targetData.datum) / segment.distance
|
||||
local slope = (targetData.datum - sourceData.datum) / segment.distance
|
||||
scaled_weight = scaled_weight / (1.0 - (slope * 5.0))
|
||||
scaled_duration = scaled_duration / (1.0 - (slope * 5.0))
|
||||
io.write(" slope: " .. slope .. "\n")
|
||||
|
||||
@@ -14,6 +14,8 @@ babel -V >/dev/null 2>&1 || { echo >&2 "Can't find babel. Add node_modules/.bin
|
||||
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||
|
||||
#documentation build src/nodejs/node_osrm.cpp --polyglot -f md -o docs/nodejs/api.md
|
||||
|
||||
# Clean up previous version
|
||||
rm -rf build/docs
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#!/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
|
||||
+21
-39
@@ -3,49 +3,31 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# should be set for debug builds
|
||||
export NPM_FLAGS=${NPM_FLAGS:-}
|
||||
if [[ ${PUBLISH} == 'On' ]]; then
|
||||
echo "PUBLISH is set to '${PUBLISH}', publishing!"
|
||||
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
|
||||
echo "dumping binary meta..."
|
||||
./node_modules/.bin/node-pre-gyp reveal ${NPM_FLAGS}
|
||||
echo "dumping binary meta..."
|
||||
./node_modules/.bin/node-pre-gyp reveal
|
||||
|
||||
# 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
|
||||
# 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
|
||||
fi
|
||||
|
||||
echo "determining publishing status..."
|
||||
|
||||
if [[ $(./scripts/travis/is_pr_merge.sh) ]]; then
|
||||
echo "Skipping publishing because this is a PR merge commit"
|
||||
./node_modules/.bin/node-pre-gyp package publish info
|
||||
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;
|
||||
echo "PUBLISH is set to '${PUBLISH}', skipping."
|
||||
fi
|
||||
|
||||
@@ -28,12 +28,14 @@ constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||
|
||||
using RTreeLeaf = extractor::EdgeBasedNode;
|
||||
using BenchStaticRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, false>::vector, false>;
|
||||
util::StaticRTree<RTreeLeaf,
|
||||
util::ShM<util::Coordinate, storage::Ownership::Container>::vector,
|
||||
storage::Ownership::Container>;
|
||||
|
||||
std::vector<util::Coordinate> loadCoordinates(const boost::filesystem::path &nodes_file)
|
||||
{
|
||||
osrm::storage::io::FileReader nodes_path_file_reader(
|
||||
nodes_file, osrm::storage::io::FileReader::HasNoFingerprint);
|
||||
storage::io::FileReader nodes_path_file_reader(nodes_file,
|
||||
storage::io::FileReader::HasNoFingerprint);
|
||||
|
||||
extractor::QueryNode current_node;
|
||||
unsigned coordinate_count = nodes_path_file_reader.ReadElementCount32();
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "partition/io.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "updater/updater.hpp"
|
||||
|
||||
#include "util/log.hpp"
|
||||
@@ -82,9 +84,9 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config,
|
||||
auto directed = partition::splitBidirectionalEdges(edge_based_edge_list);
|
||||
auto tidied =
|
||||
partition::prepareEdgesForUsageInGraph<StaticEdgeBasedGraphEdge>(std::move(directed));
|
||||
auto edge_based_graph =
|
||||
std::make_unique<partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>>(
|
||||
mlp, num_nodes, std::move(tidied));
|
||||
auto edge_based_graph = std::make_unique<
|
||||
partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>>(
|
||||
mlp, num_nodes, std::move(tidied));
|
||||
|
||||
util::Log() << "Loaded edge based graph for mapping partition ids: "
|
||||
<< edge_based_graph->GetNumberOfEdges() << " edges, "
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "engine/api/match_api.hpp"
|
||||
#include "engine/api/match_parameters.hpp"
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
#include "engine/map_matching/bayes_classifier.hpp"
|
||||
#include "engine/map_matching/sub_matching.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
@@ -145,20 +146,33 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
"InvalidValue", "Timestamps need to be monotonically increasing.", json_result);
|
||||
}
|
||||
|
||||
SubMatchingList sub_matchings;
|
||||
api::tidy::Result tidied;
|
||||
if (parameters.tidy)
|
||||
{
|
||||
// Transparently tidy match parameters, do map matching on tidied parameters.
|
||||
// Then use the mapping to restore the original <-> tidied relationship.
|
||||
tidied = api::tidy::tidy(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
tidied = api::tidy::keep_all(parameters);
|
||||
}
|
||||
|
||||
// assuming radius is the standard deviation of a normal distribution
|
||||
// that models GPS noise (in this model), x3 should give us the correct
|
||||
// search radius with > 99% confidence
|
||||
std::vector<double> search_radiuses;
|
||||
if (parameters.radiuses.empty())
|
||||
if (tidied.parameters.radiuses.empty())
|
||||
{
|
||||
search_radiuses.resize(parameters.coordinates.size(),
|
||||
search_radiuses.resize(tidied.parameters.coordinates.size(),
|
||||
routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_radiuses.resize(parameters.coordinates.size());
|
||||
std::transform(parameters.radiuses.begin(),
|
||||
parameters.radiuses.end(),
|
||||
search_radiuses.resize(tidied.parameters.coordinates.size());
|
||||
std::transform(tidied.parameters.radiuses.begin(),
|
||||
tidied.parameters.radiuses.end(),
|
||||
search_radiuses.begin(),
|
||||
[](const boost::optional<double> &maybe_radius) {
|
||||
if (maybe_radius)
|
||||
@@ -173,9 +187,9 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
});
|
||||
}
|
||||
|
||||
auto candidates_lists = GetPhantomNodesInRange(facade, parameters, search_radiuses);
|
||||
auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
|
||||
|
||||
filterCandidates(parameters.coordinates, candidates_lists);
|
||||
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
||||
if (std::all_of(candidates_lists.begin(),
|
||||
candidates_lists.end(),
|
||||
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
||||
@@ -188,8 +202,12 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
}
|
||||
|
||||
// call the actual map matching
|
||||
SubMatchingList sub_matchings = algorithms.MapMatching(
|
||||
candidates_lists, parameters.coordinates, parameters.timestamps, parameters.radiuses);
|
||||
sub_matchings =
|
||||
algorithms.MapMatching(candidates_lists,
|
||||
tidied.parameters.coordinates,
|
||||
tidied.parameters.timestamps,
|
||||
tidied.parameters.radiuses,
|
||||
parameters.gaps == api::MatchParameters::GapsType::Split);
|
||||
|
||||
if (sub_matchings.size() == 0)
|
||||
{
|
||||
@@ -220,7 +238,7 @@ Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
||||
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
|
||||
}
|
||||
|
||||
api::MatchAPI match_api{facade, parameters};
|
||||
api::MatchAPI match_api{facade, parameters, tidied};
|
||||
match_api.MakeResponse(sub_matchings, sub_routes, json_result);
|
||||
|
||||
return Status::Ok;
|
||||
|
||||
@@ -54,7 +54,8 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting)
|
||||
{
|
||||
map_matching::MatchingConfidence confidence;
|
||||
map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION);
|
||||
@@ -156,16 +157,24 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t)
|
||||
{
|
||||
|
||||
const bool gap_in_trace = [&, use_timestamps]() {
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
const bool gap_in_trace = [&]() {
|
||||
// do not determine split if wasn't asked about it
|
||||
if (allow_splitting)
|
||||
{
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time;
|
||||
// use temporal information if available to determine a split
|
||||
if (use_timestamps)
|
||||
{
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] >
|
||||
max_broken_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return t - prev_unbroken_timestamps.back() > MAX_BROKEN_STATES;
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
|
||||
@@ -416,14 +425,16 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
{
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision);
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
}
|
||||
|
||||
SubMatchingList
|
||||
@@ -432,7 +443,8 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision)
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
{
|
||||
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
@@ -440,7 +452,8 @@ mapMatching(SearchEngineData &engine_working_data,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision);
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
}
|
||||
|
||||
} // namespace routing_algorithms
|
||||
|
||||
@@ -388,21 +388,24 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
||||
BOOST_ASSERT(edge_iterator->source_coordinate.lon !=
|
||||
util::FixedLongitude{std::numeric_limits<std::int32_t>::min()});
|
||||
|
||||
const util::Coordinate target_coord{node_iterator->lon, node_iterator->lat};
|
||||
const double distance = util::coordinate_calculation::greatCircleDistance(
|
||||
edge_iterator->source_coordinate, target_coord);
|
||||
util::Coordinate source_coord(edge_iterator->source_coordinate);
|
||||
util::Coordinate target_coord{node_iterator->lon, node_iterator->lat};
|
||||
|
||||
auto weight = edge_iterator->weight_data(distance);
|
||||
auto duration = edge_iterator->duration_data(distance);
|
||||
// flip source and target coordinates if segment is in backward direction only
|
||||
if (!edge_iterator->result.forward && edge_iterator->result.backward)
|
||||
std::swap(source_coord, target_coord);
|
||||
|
||||
ExtractionSegment extracted_segment(
|
||||
edge_iterator->source_coordinate, target_coord, distance, weight, duration);
|
||||
scripting_environment.ProcessSegment(extracted_segment);
|
||||
const auto distance =
|
||||
util::coordinate_calculation::greatCircleDistance(source_coord, target_coord);
|
||||
const auto weight = edge_iterator->weight_data(distance);
|
||||
const auto duration = edge_iterator->duration_data(distance);
|
||||
|
||||
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
||||
scripting_environment.ProcessSegment(segment);
|
||||
|
||||
auto &edge = edge_iterator->result;
|
||||
edge.weight =
|
||||
std::max<EdgeWeight>(1, std::round(extracted_segment.weight * weight_multiplier));
|
||||
edge.duration = std::max<EdgeWeight>(1, std::round(extracted_segment.duration * 10.));
|
||||
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
||||
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
||||
|
||||
// assign new node id
|
||||
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
|
||||
|
||||
@@ -35,7 +35,9 @@ namespace TurnLaneType = guidance::TurnLaneType;
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
||||
const ProfileProperties &properties)
|
||||
: external_memory(extraction_containers_), fallback_to_duration(properties.fallback_to_duration)
|
||||
: external_memory(extraction_containers_),
|
||||
fallback_to_duration(properties.fallback_to_duration),
|
||||
force_split_edges(properties.force_split_edges)
|
||||
{
|
||||
// we reserved 0, 1, 2, 3 for the empty case
|
||||
string_map[MapKey("", "", "", "")] = 0;
|
||||
@@ -323,14 +325,15 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||
|
||||
// split an edge into two edges if forwards/backwards behavior differ
|
||||
const bool split_edge = in_forward_direction && in_backward_direction &&
|
||||
((parsed_way.forward_rate != parsed_way.backward_rate) ||
|
||||
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
||||
(turn_lane_id_forward != turn_lane_id_backward));
|
||||
const bool split_edge =
|
||||
in_forward_direction && in_backward_direction &&
|
||||
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
|
||||
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
||||
(turn_lane_id_forward != turn_lane_id_backward));
|
||||
|
||||
if (in_forward_direction)
|
||||
{
|
||||
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
|
||||
util::for_each_pair(
|
||||
nodes.cbegin(),
|
||||
nodes.cend(),
|
||||
@@ -355,8 +358,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
});
|
||||
}
|
||||
|
||||
if (in_backward_direction || split_edge)
|
||||
{
|
||||
if (in_backward_direction && (!in_forward_direction || split_edge))
|
||||
{ // add (backward) segments for split edges or not in forward direction
|
||||
util::for_each_pair(
|
||||
nodes.cbegin(),
|
||||
nodes.cend(),
|
||||
|
||||
@@ -247,7 +247,9 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
||||
"weight_name",
|
||||
sol::property(&ProfileProperties::SetWeightName, &ProfileProperties::GetWeightName),
|
||||
"max_turn_weight",
|
||||
sol::property(&ProfileProperties::GetMaxTurnWeight));
|
||||
sol::property(&ProfileProperties::GetMaxTurnWeight),
|
||||
"force_split_edges",
|
||||
&ProfileProperties::force_split_edges);
|
||||
|
||||
context.state.new_usertype<std::vector<std::string>>(
|
||||
"vector",
|
||||
@@ -330,12 +332,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
||||
sol::property(&ExtractionWay::GetTurnLanesForward, &ExtractionWay::SetTurnLanesForward),
|
||||
"turn_lanes_backward",
|
||||
sol::property(&ExtractionWay::GetTurnLanesBackward, &ExtractionWay::SetTurnLanesBackward),
|
||||
"roundabout",
|
||||
&ExtractionWay::roundabout,
|
||||
"circular",
|
||||
&ExtractionWay::circular,
|
||||
"is_startpoint",
|
||||
&ExtractionWay::is_startpoint,
|
||||
"duration",
|
||||
&ExtractionWay::duration,
|
||||
"weight",
|
||||
@@ -343,13 +339,26 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
||||
"road_classification",
|
||||
&ExtractionWay::road_classification,
|
||||
"forward_mode",
|
||||
sol::property(&ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode),
|
||||
sol::property([](const ExtractionWay &way) { return way.forward_travel_mode; },
|
||||
[](ExtractionWay &way, TravelMode mode) { way.forward_travel_mode = mode; }),
|
||||
"backward_mode",
|
||||
sol::property(&ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode),
|
||||
sol::property([](const ExtractionWay &way) { return way.backward_travel_mode; },
|
||||
[](ExtractionWay &way, TravelMode mode) { way.backward_travel_mode = mode; }),
|
||||
"roundabout",
|
||||
sol::property([](const ExtractionWay &way) { return way.roundabout; },
|
||||
[](ExtractionWay &way, bool flag) { way.roundabout = flag; }),
|
||||
"circular",
|
||||
sol::property([](const ExtractionWay &way) { return way.circular; },
|
||||
[](ExtractionWay &way, bool flag) { way.circular = flag; }),
|
||||
"is_startpoint",
|
||||
sol::property([](const ExtractionWay &way) { return way.is_startpoint; },
|
||||
[](ExtractionWay &way, bool flag) { way.is_startpoint = flag; }),
|
||||
"forward_restricted",
|
||||
&ExtractionWay::forward_restricted,
|
||||
sol::property([](const ExtractionWay &way) { return way.forward_restricted; },
|
||||
[](ExtractionWay &way, bool flag) { way.forward_restricted = flag; }),
|
||||
"backward_restricted",
|
||||
&ExtractionWay::backward_restricted);
|
||||
sol::property([](const ExtractionWay &way) { return way.backward_restricted; },
|
||||
[](ExtractionWay &way, bool flag) { way.backward_restricted = flag; }));
|
||||
|
||||
context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
|
||||
"source",
|
||||
|
||||
@@ -7,12 +7,14 @@ 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)
|
||||
|
||||
# ^ Make sure to set NodeJs options before including and requiring the NodeJs module.
|
||||
# Otherwise the module will use defaults (which - among many bad choices - means libc++).
|
||||
include(FindNodeJS)
|
||||
find_package(NodeJS REQUIRED)
|
||||
add_nodejs_module(node-osrm node_osrm.cpp)
|
||||
target_link_libraries(node-osrm osrm)
|
||||
@@ -20,7 +22,7 @@ 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)
|
||||
set(OSRM_BINARIES osrm-extract osrm-contract osrm-routed osrm-datastore osrm-components osrm-partition osrm-customize)
|
||||
foreach(binary ${OSRM_BINARIES})
|
||||
add_custom_command(OUTPUT ${BINDING_DIR}/${binary}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${binary}> ${BINDING_DIR}
|
||||
|
||||
+61
-83
@@ -48,15 +48,14 @@ NAN_MODULE_INIT(Engine::Init)
|
||||
Nan::Set(target, whoami, fn);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
*
|
||||
* 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:
|
||||
* The `OSRM` method is the main constructor for creating an OSRM instance.
|
||||
* An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
||||
* The documentation on `osrm-extract` and `osrm-contract` for more information.
|
||||
* Once you have a complete `network.osrm` file, you can calculate routes 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');
|
||||
@@ -78,27 +77,18 @@ NAN_MODULE_INIT(Engine::Init)
|
||||
* 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`
|
||||
* |
|
||||
* | 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::New)
|
||||
{
|
||||
if (info.IsConstructCall())
|
||||
@@ -195,6 +185,7 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
||||
Nan::AsyncQueueWorker(new Worker{self->this_, std::move(params), service, callback});
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
||||
*
|
||||
@@ -205,19 +196,14 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
||||
* *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`
|
||||
* 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.
|
||||
* @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");
|
||||
@@ -227,11 +213,13 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
||||
* console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
||||
* });
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::route) //
|
||||
{
|
||||
async(info, &argumentsToRouteParameter, &osrm::OSRM::Route, true);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* Snaps a coordinate to the street network and returns the nearest n matches.
|
||||
*
|
||||
@@ -245,11 +233,8 @@ NAN_METHOD(Engine::route) //
|
||||
* @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.
|
||||
* **`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');
|
||||
@@ -262,11 +247,13 @@ NAN_METHOD(Engine::route) //
|
||||
* console.log(response.waypoints); // array of Waypoint objects
|
||||
* });
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::nearest) //
|
||||
{
|
||||
async(info, &argumentsToNearestParameter, &osrm::OSRM::Nearest, false);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* Computes duration tables for the given locations. Allows for both symmetric and asymmetric
|
||||
* tables.
|
||||
@@ -282,11 +269,10 @@ NAN_METHOD(Engine::nearest) //
|
||||
* @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.
|
||||
* **`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.
|
||||
* **`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
|
||||
*
|
||||
* @example
|
||||
* var osrm = new OSRM('network.osrm');
|
||||
@@ -303,11 +289,13 @@ NAN_METHOD(Engine::nearest) //
|
||||
* console.log(response.destinations); // array of Waypoint objects
|
||||
* });
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::table) //
|
||||
{
|
||||
async(info, &argumentsToTableParameter, &osrm::OSRM::Table, true);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* 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
|
||||
@@ -318,11 +306,9 @@ NAN_METHOD(Engine::table) //
|
||||
*
|
||||
* @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 {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.
|
||||
@@ -334,11 +320,13 @@ NAN_METHOD(Engine::table) //
|
||||
* fs.writeFileSync('./tile.vector.pbf', response); // write the buffer to a file
|
||||
* });
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::tile)
|
||||
{
|
||||
async(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/});
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* 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
|
||||
@@ -351,31 +339,21 @@ NAN_METHOD(Engine::tile)
|
||||
* @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`).
|
||||
* 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.
|
||||
* **`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');
|
||||
@@ -390,11 +368,13 @@ NAN_METHOD(Engine::tile)
|
||||
* });
|
||||
*
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::match) //
|
||||
{
|
||||
async(info, &argumentsToMatchParameter, &osrm::OSRM::Match, true);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* 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
|
||||
@@ -406,11 +386,9 @@ NAN_METHOD(Engine::match) //
|
||||
* @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 {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.
|
||||
@@ -418,11 +396,10 @@ NAN_METHOD(Engine::match) //
|
||||
* @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.
|
||||
* **`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
|
||||
@@ -439,6 +416,7 @@ NAN_METHOD(Engine::match) //
|
||||
* console.log(response.trips); // array of Route objects
|
||||
* });
|
||||
*/
|
||||
// clang-format on
|
||||
NAN_METHOD(Engine::trip) //
|
||||
{
|
||||
async(info, &argumentsToTripParameter, &osrm::OSRM::Trip, true);
|
||||
@@ -456,7 +434,7 @@ NAN_METHOD(Engine::trip) //
|
||||
* @memberof Responses
|
||||
*
|
||||
* @param {documentation} exteral in
|
||||
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
|
||||
* [`osrm-backend`](../http.md#route)
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -467,7 +445,7 @@ NAN_METHOD(Engine::trip) //
|
||||
* @memberof Responses
|
||||
*
|
||||
* @param {documentation} exteral in
|
||||
* [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
|
||||
* [`osrm-backend`](../http.md#routeleg)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -108,12 +108,12 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
makeBisectionGraph(compressed_node_based_graph.coordinates,
|
||||
adaptToBisectionEdge(std::move(compressed_node_based_graph.edges)));
|
||||
|
||||
util::Log() << " running partition: " << config.minimum_cell_size << " " << config.balance
|
||||
util::Log() << " running partition: " << config.max_cell_sizes.front() << " " << config.balance
|
||||
<< " " << config.boundary_factor << " " << config.num_optimizing_cuts << " "
|
||||
<< config.small_component_size
|
||||
<< " # max_cell_size balance boundary cuts small_component_size";
|
||||
RecursiveBisection recursive_bisection(graph,
|
||||
config.minimum_cell_size,
|
||||
config.max_cell_sizes.front(),
|
||||
config.balance,
|
||||
config.boundary_factor,
|
||||
config.num_optimizing_cuts,
|
||||
@@ -161,11 +161,7 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
std::vector<Partition> partitions;
|
||||
std::vector<std::uint32_t> level_to_num_cells;
|
||||
std::tie(partitions, level_to_num_cells) =
|
||||
bisectionToPartition(edge_based_partition_ids,
|
||||
{config.minimum_cell_size,
|
||||
config.minimum_cell_size * 32,
|
||||
config.minimum_cell_size * 32 * 16,
|
||||
config.minimum_cell_size * 32 * 16 * 32});
|
||||
bisectionToPartition(edge_based_partition_ids, config.max_cell_sizes);
|
||||
|
||||
auto num_unconnected = removeUnconnectedBoundaryNodes(*edge_based_graph, partitions);
|
||||
util::Log() << "Fixed " << num_unconnected << " unconnected nodes";
|
||||
|
||||
+13
-10
@@ -16,6 +16,7 @@
|
||||
#include "storage/serialization.hpp"
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
#include "storage/shared_monitor.hpp"
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
@@ -55,8 +56,9 @@ namespace storage
|
||||
{
|
||||
|
||||
using RTreeLeaf = engine::datafacade::BaseDataFacade::RTreeLeaf;
|
||||
using RTreeNode =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>::TreeNode;
|
||||
using RTreeNode = util::StaticRTree<RTreeLeaf,
|
||||
util::vector_view<util::Coordinate>,
|
||||
storage::Ownership::View>::TreeNode;
|
||||
using QueryGraph = util::StaticGraph<contractor::QueryEdge::EdgeData>;
|
||||
using EdgeBasedGraph = util::StaticGraph<extractor::EdgeBasedEdge::EdgeData>;
|
||||
|
||||
@@ -364,12 +366,13 @@ void Storage::PopulateLayout(DataLayout &layout)
|
||||
intersection_file.Skip<std::uint32_t>(1); // sum_lengths
|
||||
|
||||
layout.SetBlockSize<unsigned>(DataLayout::BEARING_OFFSETS, bearing_blocks);
|
||||
layout.SetBlockSize<typename util::RangeTable<16, true>::BlockT>(DataLayout::BEARING_BLOCKS,
|
||||
bearing_blocks);
|
||||
layout.SetBlockSize<typename util::RangeTable<16, storage::Ownership::View>::BlockT>(
|
||||
DataLayout::BEARING_BLOCKS, bearing_blocks);
|
||||
|
||||
// No need to read the data
|
||||
intersection_file.Skip<unsigned>(bearing_blocks);
|
||||
intersection_file.Skip<typename util::RangeTable<16, true>::BlockT>(bearing_blocks);
|
||||
intersection_file.Skip<typename util::RangeTable<16, storage::Ownership::View>::BlockT>(
|
||||
bearing_blocks);
|
||||
|
||||
const auto num_bearings = intersection_file.ReadElementCount64();
|
||||
|
||||
@@ -694,7 +697,7 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
||||
layout.GetBlockPtr<util::Coordinate, true>(memory_ptr, DataLayout::COORDINATE_LIST);
|
||||
const auto osmnodeid_ptr =
|
||||
layout.GetBlockPtr<std::uint64_t, true>(memory_ptr, DataLayout::OSM_NODE_ID_LIST);
|
||||
util::PackedVector<OSMNodeID, true> osmnodeid_list;
|
||||
util::PackedVector<OSMNodeID, storage::Ownership::View> osmnodeid_list;
|
||||
|
||||
osmnodeid_list.reset(osmnodeid_ptr, layout.num_entries[DataLayout::OSM_NODE_ID_LIST]);
|
||||
|
||||
@@ -803,8 +806,8 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
||||
intersection_file.Skip<std::uint32_t>(1); // sum_lengths
|
||||
|
||||
std::vector<unsigned> bearing_offsets_data(bearing_blocks);
|
||||
std::vector<typename util::RangeTable<16, true>::BlockT> bearing_blocks_data(
|
||||
bearing_blocks);
|
||||
std::vector<typename util::RangeTable<16, storage::Ownership::View>::BlockT>
|
||||
bearing_blocks_data(bearing_blocks);
|
||||
|
||||
intersection_file.ReadInto(bearing_offsets_data.data(), bearing_blocks);
|
||||
intersection_file.ReadInto(bearing_blocks_data.data(), bearing_blocks);
|
||||
@@ -844,8 +847,8 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
||||
if (layout.GetBlockSize(DataLayout::BEARING_BLOCKS) > 0)
|
||||
{
|
||||
const auto bearing_blocks_ptr =
|
||||
layout.GetBlockPtr<typename util::RangeTable<16, true>::BlockT, true>(
|
||||
memory_ptr, DataLayout::BEARING_BLOCKS);
|
||||
layout.GetBlockPtr<typename util::RangeTable<16, storage::Ownership::View>::BlockT,
|
||||
true>(memory_ptr, DataLayout::BEARING_BLOCKS);
|
||||
BOOST_ASSERT(
|
||||
static_cast<std::size_t>(layout.GetBlockSize(DataLayout::BEARING_BLOCKS)) >=
|
||||
std::distance(bearing_blocks_data.begin(), bearing_blocks_data.end()) *
|
||||
|
||||
+74
-16
@@ -8,11 +8,15 @@
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <regex>
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
@@ -23,7 +27,48 @@ enum class return_code : unsigned
|
||||
exit
|
||||
};
|
||||
|
||||
return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &partition_config)
|
||||
struct MaxCellSizesArgument
|
||||
{
|
||||
std::vector<size_t> value;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const MaxCellSizesArgument &arg)
|
||||
{
|
||||
auto to_string = [](std::size_t x) { return std::to_string(x); };
|
||||
return os << boost::algorithm::join(arg.value | boost::adaptors::transformed(to_string), ",");
|
||||
}
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &values, MaxCellSizesArgument *, int)
|
||||
{
|
||||
using namespace boost::program_options;
|
||||
using namespace boost::adaptors;
|
||||
|
||||
// Make sure no previous assignment to 'v' was made.
|
||||
validators::check_first_occurrence(v);
|
||||
// Extract the first string from 'values'. If there is more than
|
||||
// one string, it's an error, and exception will be thrown.
|
||||
const std::string &s = validators::get_single_string(values);
|
||||
|
||||
std::regex re(",");
|
||||
std::vector<size_t> output;
|
||||
std::transform(std::sregex_token_iterator(s.begin(), s.end(), re, -1),
|
||||
std::sregex_token_iterator(),
|
||||
std::back_inserter(output),
|
||||
[](const auto &x) {
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<std::size_t>(x);
|
||||
}
|
||||
catch (const boost::bad_lexical_cast &)
|
||||
{
|
||||
throw validation_error(validation_error::invalid_option_value);
|
||||
}
|
||||
});
|
||||
|
||||
v = boost::any(MaxCellSizesArgument{output});
|
||||
}
|
||||
|
||||
return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &config)
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
@@ -34,40 +79,41 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &p
|
||||
config_options.add_options()
|
||||
//
|
||||
("threads,t",
|
||||
boost::program_options::value<unsigned int>(&partition_config.requested_num_threads)
|
||||
boost::program_options::value<unsigned int>(&config.requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use")
|
||||
//
|
||||
("min-cell-size",
|
||||
boost::program_options::value<std::size_t>(&partition_config.minimum_cell_size)
|
||||
->default_value(128),
|
||||
"Bisection termination citerion based on cell size")
|
||||
//
|
||||
("balance",
|
||||
boost::program_options::value<double>(&partition_config.balance)->default_value(1.2),
|
||||
boost::program_options::value<double>(&config.balance)->default_value(config.balance),
|
||||
"Balance for left and right side in single bisection")
|
||||
//
|
||||
("boundary",
|
||||
boost::program_options::value<double>(&partition_config.boundary_factor)
|
||||
->default_value(0.25),
|
||||
boost::program_options::value<double>(&config.boundary_factor)
|
||||
->default_value(config.boundary_factor),
|
||||
"Percentage of embedded nodes to contract as sources and sinks")
|
||||
//
|
||||
("optimizing-cuts",
|
||||
boost::program_options::value<std::size_t>(&partition_config.num_optimizing_cuts)
|
||||
->default_value(10),
|
||||
boost::program_options::value<std::size_t>(&config.num_optimizing_cuts)
|
||||
->default_value(config.num_optimizing_cuts),
|
||||
"Number of cuts to use for optimizing a single bisection")
|
||||
//
|
||||
("small-component-size",
|
||||
boost::program_options::value<std::size_t>(&partition_config.small_component_size)
|
||||
->default_value(1000),
|
||||
"Size threshold for small components.");
|
||||
boost::program_options::value<std::size_t>(&config.small_component_size)
|
||||
->default_value(config.small_component_size),
|
||||
"Size threshold for small components.")
|
||||
//
|
||||
("max-cell-sizes",
|
||||
boost::program_options::value<MaxCellSizesArgument>()->default_value(
|
||||
MaxCellSizesArgument{config.max_cell_sizes}),
|
||||
"Maximum cell sizes starting from the level 1. The first cell size value is a bisection "
|
||||
"termination citerion");
|
||||
|
||||
// hidden options, will be allowed on command line, but will not be
|
||||
// shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"input,i",
|
||||
boost::program_options::value<boost::filesystem::path>(&partition_config.base_path),
|
||||
boost::program_options::value<boost::filesystem::path>(&config.base_path),
|
||||
"Input file in .osrm format");
|
||||
|
||||
// positional option
|
||||
@@ -119,6 +165,18 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &p
|
||||
return return_code::fail;
|
||||
}
|
||||
|
||||
if (option_variables.count("max-cell-sizes"))
|
||||
{
|
||||
config.max_cell_sizes = option_variables["max-cell-sizes"].as<MaxCellSizesArgument>().value;
|
||||
|
||||
if (!std::is_sorted(config.max_cell_sizes.begin(), config.max_cell_sizes.end()))
|
||||
{
|
||||
util::Log(logERROR)
|
||||
<< "The maximum cell sizes array must be sorted in non-descending order.";
|
||||
return return_code::fail;
|
||||
}
|
||||
}
|
||||
|
||||
return return_code::ok;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
|
||||
using namespace osrm;
|
||||
|
||||
void removeLocks() { osrm::storage::SharedMonitor<osrm::storage::SharedDataTimestamp>::remove(); }
|
||||
void removeLocks() { storage::SharedMonitor<storage::SharedDataTimestamp>::remove(); }
|
||||
|
||||
void deleteRegion(const storage::SharedDataType region)
|
||||
{
|
||||
|
||||
@@ -81,7 +81,7 @@ void checkWeightsConsistency(
|
||||
const UpdaterConfig &config,
|
||||
const std::vector<osrm::extractor::EdgeBasedEdge> &edge_based_edge_list)
|
||||
{
|
||||
using Reader = osrm::storage::io::FileReader;
|
||||
using Reader = storage::io::FileReader;
|
||||
using OriginalEdgeData = osrm::extractor::OriginalEdgeData;
|
||||
|
||||
extractor::SegmentDataContainer segment_data;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
var path = require('path');
|
||||
|
||||
// Constants and fixtures for nodejs tests on our Monaco dataset.
|
||||
|
||||
// Somewhere in Monaco
|
||||
// http://www.openstreetmap.org/#map=18/43.73185/7.41772
|
||||
exports.three_test_coordinates = [[7.41337, 43.72956],
|
||||
[7.41546, 43.73077],
|
||||
[7.41862, 43.73216]];
|
||||
|
||||
exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2)
|
||||
|
||||
exports.test_tile = {'at': [17059, 11948, 15], 'size': 114000};
|
||||
|
||||
|
||||
// Test files generated by the routing engine; check test/data
|
||||
if (process.env.OSRM_DATA_PATH !== undefined) {
|
||||
exports.data_path = path.join(path.resolve(process.env.OSRM_DATA_PATH), "ch/monaco.osrm");
|
||||
exports.mld_data_path = path.join(path.resolve(process.env.OSRM_DATA_PATH), "mld/monaco.osrm");
|
||||
exports.corech_data_path = path.join(path.resolve(process.env.OSRM_DATA_PATH), "corech/monaco.osrm");
|
||||
console.log('Setting custom data path to ' + exports.data_path);
|
||||
} else {
|
||||
exports.data_path = path.resolve(path.join(__dirname, "../data/ch/monaco.osrm"));
|
||||
exports.mld_data_path = path.resolve(path.join(__dirname, "../data/mld/monaco.osrm"));
|
||||
exports.corech_data_path = path.resolve(path.join(__dirname, "../data/corech/monaco.osrm"));
|
||||
}
|
||||
+38
-6
@@ -1,6 +1,8 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var monaco_path = require('./constants').data_path;
|
||||
var monaco_mld_path = require('./constants').mld_data_path;
|
||||
var monaco_corech_path = require('./constants').corech_data_path;
|
||||
|
||||
test('constructor: throws if new keyword is not used', function(assert) {
|
||||
assert.plan(1);
|
||||
@@ -23,33 +25,63 @@ test('constructor: does not accept more than one parameter', function(assert) {
|
||||
test('constructor: throws if necessary files do not exist', function(assert) {
|
||||
assert.plan(1);
|
||||
assert.throws(function() { new OSRM("missing.osrm"); },
|
||||
/Invalid file paths/);
|
||||
/Error opening missing.osrm.names/);
|
||||
});
|
||||
|
||||
test('constructor: takes a shared memory argument', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM({path: berlin_path, shared_memory: false});
|
||||
var osrm = new OSRM({path: monaco_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}); },
|
||||
assert.throws(function() { 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"}); },
|
||||
assert.throws(function() { new OSRM({path: monaco_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); },
|
||||
assert.throws(function() { new OSRM(true); },
|
||||
/Parameter must be a path or options object/);
|
||||
});
|
||||
|
||||
test('constructor: throws if given an unkown algorithm', function(assert) {
|
||||
assert.plan(1);
|
||||
assert.throws(function() { new OSRM({algorithm: 'Foo', shared_memory: true}); },
|
||||
/algorithm option must be one of 'CH', 'CoreCH', or 'MLD'/);
|
||||
});
|
||||
|
||||
test('constructor: throws if given an invalid algorithm', function(assert) {
|
||||
assert.plan(1);
|
||||
assert.throws(function() { new OSRM({algorithm: 3, shared_memory: true}); },
|
||||
/algorithm option must be a string and one of 'CH', 'CoreCH', or 'MLD'/);
|
||||
});
|
||||
|
||||
test('constructor: loads MLD if given as algorithm', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM({algorithm: 'MLD', path: monaco_mld_path});
|
||||
assert.ok(osrm);
|
||||
});
|
||||
|
||||
test('constructor: loads CH if given as algorithm', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM({algorithm: 'CH', path: monaco_path});
|
||||
assert.ok(osrm);
|
||||
});
|
||||
|
||||
test('constructor: loads CoreCH if given as algorithm', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM({algorithm: 'CoreCH', path: monaco_corech_path});
|
||||
assert.ok(osrm);
|
||||
});
|
||||
|
||||
require('./route.js');
|
||||
require('./trip.js');
|
||||
require('./match.js');
|
||||
|
||||
+33
-30
@@ -1,12 +1,14 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var data_path = require('./constants').data_path;
|
||||
var three_test_coordinates = require('./constants').three_test_coordinates;
|
||||
var two_test_coordinates = require('./constants').two_test_coordinates;
|
||||
|
||||
test('match: match in Berlin', function(assert) {
|
||||
test('match: match in Monaco', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
coordinates: three_test_coordinates,
|
||||
timestamps: [1424684612, 1424684616, 1424684620]
|
||||
};
|
||||
osrm.match(options, function(err, response) {
|
||||
@@ -22,11 +24,11 @@ test('match: match in Berlin', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('match: match in Berlin without timestamps', function(assert) {
|
||||
test('match: match in Monaco without timestamps', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]]
|
||||
coordinates: three_test_coordinates
|
||||
};
|
||||
osrm.match(options, function(err, response) {
|
||||
assert.ifError(err);
|
||||
@@ -35,11 +37,11 @@ test('match: match in Berlin without timestamps', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('match: match in Berlin without geometry compression', function(assert) {
|
||||
test('match: match in Monaco without geometry compression', function(assert) {
|
||||
assert.plan(4);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
coordinates: three_test_coordinates,
|
||||
geometries: 'geojson'
|
||||
};
|
||||
osrm.match(options, function(err, response) {
|
||||
@@ -50,11 +52,11 @@ test('match: match in Berlin without geometry compression', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('match: match in Berlin with geometry compression', function(assert) {
|
||||
test('match: match in Monaco with geometry compression', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]]
|
||||
coordinates: three_test_coordinates,
|
||||
};
|
||||
osrm.match(options, function(err, response) {
|
||||
assert.ifError(err);
|
||||
@@ -63,11 +65,11 @@ test('match: match in Berlin with geometry compression', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('match: match in Berlin with speed annotations options', function(assert) {
|
||||
test('match: match in Monaco with speed annotations options', function(assert) {
|
||||
assert.plan(12);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
coordinates: three_test_coordinates,
|
||||
timestamps: [1424684612, 1424684616, 1424684620],
|
||||
radiuses: [4.07, 4.07, 4.07],
|
||||
steps: true,
|
||||
@@ -92,11 +94,12 @@ test('match: match in Berlin with speed annotations options', function(assert) {
|
||||
});
|
||||
|
||||
|
||||
test('match: match in Berlin with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
test('match: match in Monaco with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
assert.plan(12);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
timestamps: [1424684612, 1424684616, 1424684620],
|
||||
coordinates: three_test_coordinates,
|
||||
timestamps: [1424684612, 1424684616, 1424684620],
|
||||
radiuses: [4.07, 4.07, 4.07],
|
||||
steps: true,
|
||||
@@ -120,11 +123,11 @@ test('match: match in Berlin with several (duration, distance, nodes) annotation
|
||||
});
|
||||
});
|
||||
|
||||
test('match: match in Berlin with all options', function(assert) {
|
||||
test('match: match in Monaco with all options', function(assert) {
|
||||
assert.plan(8);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
coordinates: three_test_coordinates,
|
||||
timestamps: [1424684612, 1424684616, 1424684620],
|
||||
radiuses: [4.07, 4.07, 4.07],
|
||||
steps: true,
|
||||
@@ -146,42 +149,42 @@ test('match: match in Berlin with all options', function(assert) {
|
||||
|
||||
test('match: throws on missing arguments', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_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);
|
||||
var osrm = new OSRM(data_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 osrm = new OSRM(data_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]];
|
||||
options.coordinates = [three_test_coordinates[0]];
|
||||
assert.throws(function() { osrm.match(options, function(err, response) {}) },
|
||||
/At least two coordinates must be provided/);
|
||||
options.coordinates = [13.393252,52.542648];
|
||||
options.coordinates = three_test_coordinates[0]
|
||||
assert.throws(function() { osrm.match(options, function(err, response) {}) },
|
||||
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
||||
options.coordinates = [[13.393252],[52.542648]];
|
||||
options.coordinates = [three_test_coordinates[0][0], three_test_coordinates[0][1]];
|
||||
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 osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.393252,52.542648],[13.39478,52.543079],[13.397389,52.542107]],
|
||||
coordinates: three_test_coordinates,
|
||||
timestamps: 'timestamps'
|
||||
};
|
||||
assert.throws(function() { osrm.match(options, function(err, response) {}) },
|
||||
|
||||
+12
-9
@@ -1,12 +1,15 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var data_path = require('./constants').data_path;
|
||||
var three_test_coordinates = require('./constants').three_test_coordinates;
|
||||
var two_test_coordinates = require('./constants').two_test_coordinates;
|
||||
|
||||
|
||||
test('nearest', function(assert) {
|
||||
assert.plan(4);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
osrm.nearest({
|
||||
coordinates: [[13.333086, 52.4224]]
|
||||
coordinates: [three_test_coordinates[0]]
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
assert.equal(result.waypoints.length, 1);
|
||||
@@ -17,9 +20,9 @@ test('nearest', function(assert) {
|
||||
|
||||
test('nearest: can ask for multiple nearest pts', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
osrm.nearest({
|
||||
coordinates: [[13.333086, 52.4224]],
|
||||
coordinates: [three_test_coordinates[0]],
|
||||
number: 3
|
||||
}, function(err, result) {
|
||||
assert.ifError(err);
|
||||
@@ -29,19 +32,19 @@ test('nearest: can ask for multiple nearest pts', function(assert) {
|
||||
|
||||
test('nearest: throws on invalid args', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_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];
|
||||
options.coordinates = [43.73072];
|
||||
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]];
|
||||
options.coordinates = [three_test_coordinates[0], three_test_coordinates[1]];
|
||||
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
|
||||
/Exactly one coordinate pair must be provided/);
|
||||
options.coordinates = [[13.333086, 52.4224]];
|
||||
options.coordinates = [three_test_coordinates[0]];
|
||||
options.number = 3.14159;
|
||||
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
|
||||
/Number must be an integer greater than or equal to 1/);
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
var path = require('path');
|
||||
|
||||
if (process.env.OSRM_DATA_PATH !== undefined) {
|
||||
exports.data_path = path.join(path.resolve(process.env.OSRM_DATA_PATH), "ch/berlin.osrm");
|
||||
console.log('Setting custom data path to ' + exports.data_path);
|
||||
} else {
|
||||
exports.data_path = path.resolve(path.join(__dirname, "../data/ch/berlin.osrm"));
|
||||
}
|
||||
+106
-77
@@ -1,10 +1,39 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var monaco_path = require('./constants').data_path;
|
||||
var monaco_mld_path = require('./constants').mld_data_path;
|
||||
var monaco_corech_path = require('./constants').corech_data_path;
|
||||
var three_test_coordinates = require('./constants').three_test_coordinates;
|
||||
var two_test_coordinates = require('./constants').two_test_coordinates;
|
||||
|
||||
test('route: routes Berlin', function(assert) {
|
||||
|
||||
test('route: routes Monaco', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
osrm.route({coordinates: two_test_coordinates}, 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: routes Monaco on MLD', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM({path: monaco_mld_path, algorithm: 'MLD'});
|
||||
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: routes Monaco on CoreCH', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM({path: monaco_corech_path, algorithm: 'CoreCH'});
|
||||
osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, function(err, route) {
|
||||
assert.ifError(err);
|
||||
assert.ok(route.waypoints);
|
||||
@@ -16,19 +45,19 @@ test('route: routes Berlin', function(assert) {
|
||||
|
||||
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]]}) },
|
||||
var osrm = new OSRM(monaco_path);
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}) },
|
||||
/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)},
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, true)},
|
||||
/last argument must be a callback function/);
|
||||
});
|
||||
|
||||
test('route: provides no alternatives by default, but when requested', function(assert) {
|
||||
test('route: provides no alternatives by default, but when requested it may (not guaranteed)', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var options = {coordinates: [[13.302383,52.490516], [13.418427,52.522070]]};
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {coordinates: two_test_coordinates};
|
||||
|
||||
osrm.route(options, function(err, route) {
|
||||
assert.ifError(err);
|
||||
@@ -39,53 +68,53 @@ test('route: provides no alternatives by default, but when requested', function(
|
||||
osrm.route(options, function(err, route) {
|
||||
assert.ifError(err);
|
||||
assert.ok(route.routes);
|
||||
assert.equal(route.routes.length, 2);
|
||||
assert.ok(route.routes.length >= 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('route: throws with bad params', function(assert) {
|
||||
assert.plan(11);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_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) {}) },
|
||||
assert.throws(function() { osrm.route({coordinates: [[three_test_coordinates[0]], [three_test_coordinates[1]]]}, 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) {}) },
|
||||
assert.throws(function() { osrm.route({coordinates: [[true, 'stringish'], three_test_coordinates[1]]}, 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) {}) },
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, 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) {}) });
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, steps: null}, function(err, route) {}) });
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, annotations: null}, function(err, route) {}) });
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
alternateRoute: false,
|
||||
hints: [13.438640, 52.519930]
|
||||
hints: three_test_coordinates[0]
|
||||
};
|
||||
assert.throws(function() { osrm.route(options, function(err, route) {}) },
|
||||
/Hint must be null or string/);
|
||||
});
|
||||
|
||||
test('route: routes Berlin using shared memory', function(assert) {
|
||||
test('route: routes Monaco 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) {
|
||||
osrm.route({coordinates: two_test_coordinates}, function(err, route) {
|
||||
assert.ifError(err);
|
||||
assert.ok(Array.isArray(route.routes));
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with geometry compression', function(assert) {
|
||||
test('route: routes Monaco with geometry compression', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
};
|
||||
osrm.route(options, function(err, route) {
|
||||
assert.ifError(err);
|
||||
@@ -93,11 +122,11 @@ test('route: routes Berlin with geometry compression', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin without geometry compression', function(assert) {
|
||||
test('route: routes Monaco without geometry compression', function(assert) {
|
||||
assert.plan(4);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
geometries: 'geojson'
|
||||
};
|
||||
osrm.route(options, function(err, route) {
|
||||
@@ -110,9 +139,9 @@ test('route: routes Berlin without geometry compression', function(assert) {
|
||||
|
||||
test('Test polyline6 geometries option', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: false,
|
||||
overview: 'false',
|
||||
geometries: 'polyline6',
|
||||
@@ -128,11 +157,11 @@ test('Test polyline6 geometries option', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with speed annotations options', function(assert) {
|
||||
test('route: routes Monaco with speed annotations options', function(assert) {
|
||||
assert.plan(17);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: false,
|
||||
overview: 'false',
|
||||
geometries: 'polyline',
|
||||
@@ -167,16 +196,16 @@ test('route: routes Berlin with speed annotations options', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
test('route: routes Monaco with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
assert.plan(17);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: false,
|
||||
overview: 'false',
|
||||
geometries: 'polyline',
|
||||
steps: true,
|
||||
annotations: ['duration','distance','nodes']
|
||||
annotations: ['duration', 'distance', 'nodes']
|
||||
};
|
||||
osrm.route(options, function(err, first) {
|
||||
assert.ifError(err);
|
||||
@@ -206,11 +235,11 @@ test('route: routes Berlin with several (duration, distance, nodes) annotations
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with options', function(assert) {
|
||||
test('route: routes Monaco with options', function(assert) {
|
||||
assert.plan(11);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: false,
|
||||
overview: 'false',
|
||||
geometries: 'polyline',
|
||||
@@ -239,11 +268,11 @@ test('route: routes Berlin with options', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with options', function(assert) {
|
||||
test('route: routes Monaco with options', function(assert) {
|
||||
assert.plan(11);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: false,
|
||||
overview: 'false',
|
||||
geometries: 'polyline',
|
||||
@@ -274,39 +303,39 @@ test('route: routes Berlin with options', function(assert) {
|
||||
|
||||
test('route: invalid route options', function(assert) {
|
||||
assert.plan(8);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
continue_straight: []
|
||||
}, function(err, route) {}); },
|
||||
/must be boolean/);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
alternatives: []
|
||||
}, function(err, route) {}); },
|
||||
/must be boolean/);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
geometries: 'maybe'
|
||||
}, function(err, route) {}); },
|
||||
/'geometries' param must be one of \[polyline, polyline6, geojson\]/);
|
||||
@@ -318,9 +347,9 @@ test('route: invalid route options', function(assert) {
|
||||
|
||||
test('route: integer bearing values no longer supported', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
bearings: [200, 250],
|
||||
};
|
||||
assert.throws(function() { osrm.route(options, function(err, route) {}); },
|
||||
@@ -329,9 +358,9 @@ test('route: integer bearing values no longer supported', function(assert) {
|
||||
|
||||
test('route: valid bearing values', function(assert) {
|
||||
assert.plan(4);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
bearings: [[200, 180], [250, 180]],
|
||||
};
|
||||
osrm.route(options, function(err, route) {
|
||||
@@ -347,44 +376,44 @@ test('route: valid bearing values', function(assert) {
|
||||
|
||||
test('route: invalid bearing values', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
bearings: [Infinity, Infinity],
|
||||
}, function(err, route) {}) },
|
||||
/Bearing must be an array of \[bearing, range\] or null/);
|
||||
});
|
||||
|
||||
test('route: routes Berlin with hints', function(assert) {
|
||||
test('route: routes Monaco with hints', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
|
||||
coordinates: two_test_coordinates,
|
||||
};
|
||||
osrm.route(options, function(err, first) {
|
||||
assert.ifError(err);
|
||||
@@ -401,11 +430,11 @@ test('route: routes Berlin with hints', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: routes Berlin with null hints', function(assert) {
|
||||
test('route: routes Monaco with null hints', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
hints: [null, null]
|
||||
};
|
||||
osrm.route(options, function(err, route) {
|
||||
@@ -415,22 +444,22 @@ test('route: routes Berlin with null hints', function(assert) {
|
||||
|
||||
test('route: throws on bad hints', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
hints: ['', '']
|
||||
}, function(err, route) {})}, /Hint cannot be an empty string/);
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
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) {
|
||||
test('route: routes Monaco with valid radius values', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
radiuses: [100, 100]
|
||||
};
|
||||
osrm.route(options, function(err, route) {
|
||||
@@ -448,23 +477,23 @@ test('route: routes Berlin with valid radius values', function(assert) {
|
||||
|
||||
test('route: throws on bad radiuses', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
radiuses: [10, 10]
|
||||
};
|
||||
assert.throws(function() { osrm.route({
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]],
|
||||
coordinates: two_test_coordinates,
|
||||
radiuses: [10]
|
||||
}, function(err, route) {}) },
|
||||
/Radiuses array must have the same length as coordinates array/);
|
||||
|
||||
+29
-22
@@ -1,12 +1,15 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var data_path = require('./constants').data_path;
|
||||
var three_test_coordinates = require('./constants').three_test_coordinates;
|
||||
var two_test_coordinates = require('./constants').two_test_coordinates;
|
||||
|
||||
test('table: distance table in Berlin', function(assert) {
|
||||
assert.plan(9);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
|
||||
test('table: distance table in Monaco', function(assert) {
|
||||
assert.plan(11);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
|
||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]]
|
||||
};
|
||||
osrm.table(options, function(err, table) {
|
||||
assert.ifError(err);
|
||||
@@ -23,6 +26,8 @@ test('table: distance table in Berlin', function(assert) {
|
||||
} else {
|
||||
// everything else is non-zero
|
||||
assert.notEqual(0, column[j], 'other entries must be non-zero');
|
||||
// and finite (not nan, inf etc.)
|
||||
assert.ok(Number.isFinite(column[j]), 'distance is finite number');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,11 +35,11 @@ test('table: distance table in Berlin', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('table: distance table in Berlin with sources/destinations', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
test('table: distance table in Monaco with sources/destinations', function(assert) {
|
||||
assert.plan(7);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]],
|
||||
sources: [0],
|
||||
destinations: [0,1]
|
||||
};
|
||||
@@ -53,6 +58,8 @@ test('table: distance table in Berlin with sources/destinations', function(asser
|
||||
} else {
|
||||
// everything else is non-zero
|
||||
assert.notEqual(0, column[j], 'other entries must be non-zero');
|
||||
// and finite (not nan, inf etc.)
|
||||
assert.ok(Number.isFinite(column[j]), 'distance is finite number');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,24 +69,24 @@ test('table: distance table in Berlin with sources/destinations', function(asser
|
||||
|
||||
test('table: throws on invalid arguments', function(assert) {
|
||||
assert.plan(14);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_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]];
|
||||
options.coordinates = [three_test_coordinates[0]];
|
||||
assert.throws(function() { osrm.table(options, function(err, response) {}) },
|
||||
/At least two coordinates must be provided/);
|
||||
options.coordinates = [13.393252,52.542648];
|
||||
options.coordinates = three_test_coordinates[0];
|
||||
assert.throws(function() { osrm.table(options, function(err, response) {}) },
|
||||
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
||||
options.coordinates = [[13.393252],[52.542648]];
|
||||
options.coordinates = [three_test_coordinates[0][0], three_test_coordinates[0][1]];
|
||||
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.coordinates = two_test_coordinates;
|
||||
options.sources = true;
|
||||
assert.throws(function() { osrm.table(options, function(err, response) {}) },
|
||||
/Sources must be an array of indices \(or undefined\)/);
|
||||
@@ -110,22 +117,22 @@ test('table: throws on invalid arguments', function(assert) {
|
||||
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) {}) },
|
||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, 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);
|
||||
var osrm = new OSRM(data_path);
|
||||
assert.throws(function() { osrm.table(null, function() {}); },
|
||||
/First arg must be an object/);
|
||||
});
|
||||
|
||||
test('table: distance table in Berlin with hints', function(assert) {
|
||||
test('table: distance table in Monaco with hints', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
generate_hints: true // true is default but be explicit here
|
||||
};
|
||||
osrm.table(options, function(err, table) {
|
||||
@@ -141,11 +148,11 @@ test('table: distance table in Berlin with hints', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('table: distance table in Berlin without hints', function(assert) {
|
||||
test('table: distance table in Monaco without hints', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
generate_hints: false // true is default
|
||||
};
|
||||
osrm.table(options, function(err, table) {
|
||||
|
||||
+15
-13
@@ -1,23 +1,25 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = "test/data/berlin-latest.osrm";
|
||||
var data_path = require('./constants').data_path;
|
||||
var tile = require('./constants').test_tile;
|
||||
|
||||
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) {
|
||||
var osrm = new OSRM(data_path);
|
||||
osrm.tile(tile.at, function(err, result) {
|
||||
assert.ifError(err);
|
||||
assert.ok(result.length > 35000);
|
||||
assert.ok(result.length > tile.size);
|
||||
});
|
||||
});
|
||||
|
||||
// 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);
|
||||
});
|
||||
test.test('tile interface pre-conditions', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(data_path);
|
||||
|
||||
assert.throws(function() { osrm.tile(null, function(err, result) {}) }, /must be an array \[x, y, z\]/);
|
||||
assert.throws(function() { osrm.tile([], function(err, result) {}) }, /must be an array \[x, y, z\]/);
|
||||
assert.throws(function() { osrm.tile([[]], function(err, result) {}) }, /must be an array \[x, y, z\]/);
|
||||
assert.throws(function() { osrm.tile(undefined, function(err, result) {}) }, /must be an array \[x, y, z\]/);
|
||||
assert.throws(function() { osrm.tile(17059, 11948, 15, function(err, result) {}) }, /must be an array \[x, y, z\]/);
|
||||
assert.throws(function() { osrm.tile([17059, 11948, -15], function(err, result) {}) }, /must be unsigned/);
|
||||
});
|
||||
|
||||
+50
-56
@@ -1,11 +1,14 @@
|
||||
var OSRM = require('../../');
|
||||
var test = require('tape');
|
||||
var berlin_path = require('./osrm-data-path').data_path;
|
||||
var data_path = require('./constants').data_path;
|
||||
var three_test_coordinates = require('./constants').three_test_coordinates;
|
||||
var two_test_coordinates = require('./constants').two_test_coordinates;
|
||||
|
||||
test('trip: trip in Berlin', function(assert) {
|
||||
|
||||
test('trip: trip in Monaco', 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) {
|
||||
var osrm = new OSRM(data_path);
|
||||
osrm.trip({coordinates: two_test_coordinates}, function(err, trip) {
|
||||
assert.ifError(err);
|
||||
for (t = 0; t < trip.trips.length; t++) {
|
||||
assert.ok(trip.trips[t].geometry);
|
||||
@@ -13,28 +16,25 @@ test('trip: trip in Berlin', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
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]]
|
||||
};
|
||||
test('trip: trip with many locations in Monaco', function(assert) {
|
||||
assert.plan(2);
|
||||
|
||||
var many = 5;
|
||||
|
||||
var osrm = new OSRM(data_path);
|
||||
var opts = {coordinates: three_test_coordinates.slice(0, many)};
|
||||
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]]}) },
|
||||
var osrm = new OSRM(data_path);
|
||||
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}) },
|
||||
/Two arguments required/);
|
||||
assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
|
||||
/First arg must be an object/);
|
||||
@@ -42,7 +42,7 @@ test('trip: throws with too few or invalid args', function(assert) {
|
||||
|
||||
test('trip: throws with bad params', function(assert) {
|
||||
assert.plan(14);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
assert.throws(function () { osrm.trip({coordinates: []}, function(err) {}) });
|
||||
assert.throws(function() { osrm.trip({}, function(err, trip) {}) },
|
||||
/Must provide a coordinates property/);
|
||||
@@ -51,22 +51,21 @@ test('trip: throws with bad params', function(assert) {
|
||||
}, function(err, trip) {}) },
|
||||
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
||||
assert.throws(function() { osrm.trip({
|
||||
coordinates: [13.438640, 52.519930]
|
||||
coordinates: three_test_coordinates[0]
|
||||
}, function(err, trip) {}) },
|
||||
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
||||
assert.throws(function() { osrm.trip({
|
||||
coordinates: [[13.438640], [52.519930]]
|
||||
coordinates: [three_test_coordinates[0][0], three_test_coordinates[0][1]]
|
||||
}, 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]],
|
||||
coordinates: two_test_coordinates,
|
||||
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]
|
||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]],
|
||||
hints: three_test_coordinates[0]
|
||||
};
|
||||
assert.throws(function() { osrm.trip(options, function(err, trip) {}); },
|
||||
/Hint must be null or string/);
|
||||
@@ -96,10 +95,10 @@ test('trip: throws with bad params', function(assert) {
|
||||
/'roundtrip' param must be a boolean/);
|
||||
});
|
||||
|
||||
test('trip: routes Berlin using shared memory', function(assert) {
|
||||
test('trip: routes Monaco 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) {
|
||||
osrm.trip({coordinates: two_test_coordinates}, function(err, trip) {
|
||||
assert.ifError(err);
|
||||
for (t = 0; t < trip.trips.length; t++) {
|
||||
assert.ok(trip.trips[t].geometry);
|
||||
@@ -107,11 +106,11 @@ test('trip: routes Berlin using shared memory', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: routes Berlin with hints', function(assert) {
|
||||
test('trip: routes Monaco with hints', function(assert) {
|
||||
assert.plan(5);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
steps: false
|
||||
};
|
||||
osrm.trip(options, function(err, first) {
|
||||
@@ -130,11 +129,11 @@ test('trip: routes Berlin with hints', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: trip through Berlin with geometry compression', function(assert) {
|
||||
test('trip: trip through Monaco with geometry compression', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]]
|
||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]]
|
||||
};
|
||||
osrm.trip(options, function(err, trip) {
|
||||
assert.ifError(err);
|
||||
@@ -144,11 +143,11 @@ test('trip: trip through Berlin with geometry compression', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: trip through Berlin without geometry compression', function(assert) {
|
||||
test('trip: trip through Monaco without geometry compression', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
geometries: 'geojson'
|
||||
};
|
||||
osrm.trip(options, function(err, trip) {
|
||||
@@ -159,11 +158,11 @@ test('trip: trip through Berlin without geometry compression', function(assert)
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: trip through Berlin with speed annotations options', function(assert) {
|
||||
test('trip: trip through Monaco with speed annotations options', function(assert) {
|
||||
assert.plan(12);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
steps: true,
|
||||
annotations: ['speed'],
|
||||
overview: 'false'
|
||||
@@ -186,11 +185,11 @@ test('trip: trip through Berlin with speed annotations options', function(assert
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: trip through Berlin with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
test('trip: trip through Monaco with several (duration, distance, nodes) annotations options', function(assert) {
|
||||
assert.plan(12);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
steps: true,
|
||||
annotations: ['duration', 'distance', 'nodes'],
|
||||
overview: 'false'
|
||||
@@ -213,11 +212,11 @@ test('trip: trip through Berlin with several (duration, distance, nodes) annotat
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: trip through Berlin with options', function(assert) {
|
||||
test('trip: trip through Monaco with options', function(assert) {
|
||||
assert.plan(6);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
steps: true,
|
||||
annotations: true,
|
||||
overview: 'false'
|
||||
@@ -234,12 +233,11 @@ test('trip: trip through Berlin with options', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('trip: routes Berlin with null hints', function(assert) {
|
||||
test('trip: routes Monaco with null hints', function(assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
printInstructions: false,
|
||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]],
|
||||
hints: [null, null]
|
||||
};
|
||||
osrm.trip(options, function(err, second) {
|
||||
@@ -249,11 +247,11 @@ test('trip: routes Berlin with null hints', function(assert) {
|
||||
|
||||
test('trip: service combinations that are not implemented', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(berlin_path);
|
||||
var osrm = new OSRM(data_path);
|
||||
|
||||
// fixed start, non-roundtrip
|
||||
var options = {
|
||||
coordinates: [[13.43864,52.51993],[13.415852,52.513191]],
|
||||
coordinates: two_test_coordinates,
|
||||
source: 'first',
|
||||
roundtrip: false
|
||||
};
|
||||
@@ -278,10 +276,10 @@ test('trip: service combinations that are not implemented', function(assert) {
|
||||
});
|
||||
|
||||
test('trip: fixed start and end combinations', function(assert) {
|
||||
var osrm = new OSRM(berlin_path);
|
||||
|
||||
var osrm = new OSRM(data_path);
|
||||
|
||||
var options = {
|
||||
coordinates: [[13.36761474609375,52.51663871100423],[13.374481201171875,52.506191342034576]],
|
||||
coordinates: two_test_coordinates,
|
||||
source: 'first',
|
||||
destination: 'last',
|
||||
roundtrip: false,
|
||||
@@ -291,10 +289,8 @@ test('trip: fixed start and end combinations', function(assert) {
|
||||
// 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]));
|
||||
});
|
||||
|
||||
@@ -304,9 +300,7 @@ test('trip: fixed start and end combinations', function(assert) {
|
||||
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]));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
||||
edges.push_back(Edge{m.target, m.start, m.weight, false, true});
|
||||
}
|
||||
std::sort(edges.begin(), edges.end());
|
||||
return partition::MultiLevelGraph<EdgeData, false>(mlp, max_id + 1, edges);
|
||||
return partition::MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(
|
||||
mlp, max_id + 1, edges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ BOOST_AUTO_TEST_CASE(two_level_test)
|
||||
|
||||
CellStorage storage(mlp, graph);
|
||||
CellCustomizer customizer(mlp);
|
||||
CellCustomizer::Heap heap(graph.GetNumberOfNodes());
|
||||
|
||||
auto cell_1_0 = storage.GetCell(1, 0);
|
||||
auto cell_1_1 = storage.GetCell(1, 1);
|
||||
@@ -79,8 +81,8 @@ BOOST_AUTO_TEST_CASE(two_level_test)
|
||||
REQUIRE_SIZE_RANGE(cell_1_1.GetOutWeight(2), 2);
|
||||
REQUIRE_SIZE_RANGE(cell_1_1.GetInWeight(3), 2);
|
||||
|
||||
customizer.Customize(graph, storage, 1, 0);
|
||||
customizer.Customize(graph, storage, 1, 1);
|
||||
customizer.Customize(graph, heap, storage, 1, 0);
|
||||
customizer.Customize(graph, heap, storage, 1, 1);
|
||||
|
||||
// cell 0
|
||||
// check row source -> destination
|
||||
@@ -202,14 +204,15 @@ BOOST_AUTO_TEST_CASE(four_levels_test)
|
||||
REQUIRE_SIZE_RANGE(cell_3_0.GetDestinationNodes(), 0);
|
||||
|
||||
CellCustomizer customizer(mlp);
|
||||
CellCustomizer::Heap heap(graph.GetNumberOfNodes());
|
||||
|
||||
customizer.Customize(graph, storage, 1, 0);
|
||||
customizer.Customize(graph, storage, 1, 1);
|
||||
customizer.Customize(graph, storage, 1, 2);
|
||||
customizer.Customize(graph, storage, 1, 3);
|
||||
customizer.Customize(graph, heap, storage, 1, 0);
|
||||
customizer.Customize(graph, heap, storage, 1, 1);
|
||||
customizer.Customize(graph, heap, storage, 1, 2);
|
||||
customizer.Customize(graph, heap, storage, 1, 3);
|
||||
|
||||
customizer.Customize(graph, storage, 2, 0);
|
||||
customizer.Customize(graph, storage, 2, 1);
|
||||
customizer.Customize(graph, heap, storage, 2, 0);
|
||||
customizer.Customize(graph, heap, storage, 2, 1);
|
||||
|
||||
// level 1
|
||||
// cell 0
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "engine/api/match_parameters_tidy.hpp"
|
||||
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(tidy_test)
|
||||
|
||||
using namespace osrm;
|
||||
using namespace osrm::util;
|
||||
using namespace osrm::engine::api;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_item_trace_already_tidied_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15.;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
|
||||
BOOST_CHECK(result.can_be_removed[0] == false);
|
||||
BOOST_CHECK(result.can_be_removed[1] == false);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_item_trace_needs_tidiying_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 5000;
|
||||
thresholds.duration_in_seconds = 5 * 60;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[1], true);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207994}, FloatLatitude{52.446380});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207995}, FloatLatitude{52.446381});
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231659}, FloatLatitude{52.465417});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231660}, FloatLatitude{52.465417});
|
||||
|
||||
params.timestamps.emplace_back(1477090402);
|
||||
params.timestamps.emplace_back(1477090403);
|
||||
params.timestamps.emplace_back(1477090404);
|
||||
|
||||
params.timestamps.emplace_back(1477090661);
|
||||
params.timestamps.emplace_back(1477090662);
|
||||
params.timestamps.emplace_back(1477090663);
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||
|
||||
const auto redundant = result.can_be_removed.count();
|
||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
||||
{
|
||||
MatchParameters params;
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207993}, FloatLatitude{52.446379});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207994}, FloatLatitude{52.446380});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.207995}, FloatLatitude{52.446381});
|
||||
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231658}, FloatLatitude{52.465416});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231659}, FloatLatitude{52.465417});
|
||||
params.coordinates.emplace_back(FloatLongitude{13.231660}, FloatLatitude{52.465417});
|
||||
|
||||
tidy::Thresholds thresholds;
|
||||
thresholds.distance_in_meters = 15;
|
||||
thresholds.duration_in_seconds = 5;
|
||||
|
||||
auto result = tidy::tidy(params, thresholds);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||
|
||||
const auto redundant = result.can_be_removed.count();
|
||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -38,7 +38,7 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
||||
edges.push_back(Edge{m.target, m.source, false, true});
|
||||
}
|
||||
std::sort(edges.begin(), edges.end());
|
||||
return MultiLevelGraph<EdgeData, false>(mlp, max_id + 1, edges);
|
||||
return MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(mlp, max_id + 1, edges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,11 @@ BOOST_AUTO_TEST_SUITE(multi_level_graph)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
{
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
std::vector<CellID> l1{{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6}};
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};
|
||||
// node: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
std::vector<CellID> l1{{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6}};
|
||||
std::vector<CellID> l2{{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4}};
|
||||
std::vector<CellID> l3{{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}};
|
||||
std::vector<CellID> l4{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}};
|
||||
MultiLevelPartition mlp{{l1, l2, l3, l4}, {7, 5, 3, 2}};
|
||||
|
||||
std::vector<MockEdge> edges = {
|
||||
@@ -69,7 +69,8 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
{9, 8}, // i i i i
|
||||
{10, 11}, // i i i i
|
||||
{11, 10}, // i i i i
|
||||
{11, 12} // b b b b
|
||||
{11, 12}, // b b b b
|
||||
{12, 13} // i i i i
|
||||
};
|
||||
|
||||
auto graph = makeGraph(mlp, edges);
|
||||
@@ -97,7 +98,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
// the union of border and internal edge needs to equal the adjacent edges
|
||||
for (auto level : util::irange<LevelID>(0, 4))
|
||||
{
|
||||
for (auto node : util::irange<NodeID>(0, 13))
|
||||
for (auto node : util::irange<NodeID>(0, 14))
|
||||
{
|
||||
const auto adjacent = graph.GetAdjacentEdgeRange(node);
|
||||
const auto border = graph.GetBorderEdgeRange(level, node);
|
||||
@@ -122,6 +123,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 11).size(), 2);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 0).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 1).size(), 0);
|
||||
@@ -136,6 +138,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 11).size(), 2);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 0).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 1).size(), 0);
|
||||
@@ -150,6 +153,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 11).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 13).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 0).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 1).size(), 0);
|
||||
@@ -164,6 +168,7 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 10).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 11).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(3, 12).size(), 1);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(4, 13).size(), 0);
|
||||
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(1, 0), graph.FindEdge(0, 4));
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(1, 3), graph.FindEdge(3, 7));
|
||||
@@ -194,4 +199,25 @@ BOOST_AUTO_TEST_CASE(check_edges_sorting)
|
||||
CHECK_EQUAL_RANGE(graph.GetBorderEdgeRange(4, 12), graph.FindEdge(12, 11));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(check_last_internal_edge)
|
||||
{
|
||||
// a--b--c--d
|
||||
std::vector<CellID> l1{{0, 0, 1, 1}};
|
||||
std::vector<CellID> l2{{0, 0, 1, 1}};
|
||||
MultiLevelPartition mlp{{l1, l2}, {2, 2}};
|
||||
|
||||
std::vector<MockEdge> edges = {{0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 3}, {3, 2}};
|
||||
|
||||
auto graph = makeGraph(mlp, edges);
|
||||
|
||||
auto all_edges = graph.GetAdjacentEdgeRange(3);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetBorderEdgeRange(0, 3), all_edges);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(1, 3).size(), 0);
|
||||
BOOST_CHECK_EQUAL(graph.GetBorderEdgeRange(2, 3).size(), 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetInternalEdgeRange(0, 3).size(), 0);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetInternalEdgeRange(1, 3), all_edges);
|
||||
CHECK_EQUAL_COLLECTIONS(graph.GetInternalEdgeRange(2, 3), all_edges);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -12,7 +12,7 @@ using namespace osrm::util;
|
||||
// Verify that the packed vector behaves as expected
|
||||
BOOST_AUTO_TEST_CASE(insert_and_retrieve_packed_test)
|
||||
{
|
||||
PackedVector<OSMNodeID, false> packed_ids;
|
||||
PackedVector<OSMNodeID, osrm::storage::Ownership::Container> packed_ids;
|
||||
std::vector<OSMNodeID> original_ids;
|
||||
|
||||
const constexpr std::size_t num_test_cases = 399;
|
||||
@@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(insert_and_retrieve_packed_test)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(packed_vector_capacity_test)
|
||||
{
|
||||
PackedVector<OSMNodeID, false> packed_vec;
|
||||
PackedVector<OSMNodeID, osrm::storage::Ownership::Container> packed_vec;
|
||||
const std::size_t original_size = packed_vec.capacity();
|
||||
std::vector<OSMNodeID> dummy_vec;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ using namespace osrm;
|
||||
using namespace osrm::util;
|
||||
|
||||
constexpr unsigned BLOCK_SIZE = 16;
|
||||
typedef RangeTable<BLOCK_SIZE, false> TestRangeTable;
|
||||
typedef RangeTable<BLOCK_SIZE, osrm::storage::Ownership::Container> TestRangeTable;
|
||||
|
||||
void ConstructionTest(stxxl::vector<unsigned> lengths, std::vector<unsigned> offsets)
|
||||
{
|
||||
|
||||
@@ -70,8 +70,8 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
|
||||
std::shuffle(order.begin(), order.end(), g);
|
||||
}
|
||||
|
||||
typename ShM<TestNodeArrayEntry, false>::vector nodes;
|
||||
typename ShM<TestEdgeArrayEntry, false>::vector edges;
|
||||
std::vector<TestNodeArrayEntry> nodes;
|
||||
std::vector<TestEdgeArrayEntry> edges;
|
||||
std::vector<unsigned> lengths;
|
||||
std::vector<unsigned> order;
|
||||
};
|
||||
|
||||
@@ -42,10 +42,11 @@ constexpr uint32_t TEST_LEAF_NODE_SIZE = 64;
|
||||
using TestData = extractor::EdgeBasedNode;
|
||||
using TestStaticRTree = StaticRTree<TestData,
|
||||
std::vector<Coordinate>,
|
||||
false,
|
||||
osrm::storage::Ownership::Container,
|
||||
TEST_BRANCHING_FACTOR,
|
||||
TEST_LEAF_NODE_SIZE>;
|
||||
using MiniStaticRTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 128>;
|
||||
using MiniStaticRTree =
|
||||
StaticRTree<TestData, std::vector<Coordinate>, osrm::storage::Ownership::Container, 2, 128>;
|
||||
|
||||
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||
constexpr unsigned RANDOM_SEED = 42;
|
||||
@@ -273,7 +274,8 @@ void construction_test(const std::string &prefix, FixtureT *fixture)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_tiny, TestRandomGraphFixture_10_30)
|
||||
{
|
||||
using TinyTestTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 64>;
|
||||
using TinyTestTree =
|
||||
StaticRTree<TestData, std::vector<Coordinate>, osrm::storage::Ownership::Container, 2, 64>;
|
||||
construction_test<TinyTestTree>("test_tiny", this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user