Compare commits

..

17 Commits

Author SHA1 Message Date
Patrick Niklaus 577801ad38 Bump version to RC4 2017-10-26 19:54:23 +00:00
Daniel J. Hofmann 7a86b7985f Adds cardinal_directions flag to profiles and disables ref-rewriting by default 2017-10-26 19:51:09 +00:00
Denis Koronchik 41551119f2 Review fixes 2017-10-26 19:51:00 +00:00
Denis Koronchik 521636c854 Work on forward/backward ref's support 2017-10-26 19:50:49 +00:00
Patrick Niklaus 6172dffd35 Bump version 2017-10-24 10:42:59 +00:00
Michael Krasnyk 57099e4a85 Add unclassified roads to restricted_highway_whitelist, #4631 2017-10-24 10:04:44 +00:00
Patrick Niklaus 6be468bdb4 Contract the exclude-flag sub-graphs as well 2017-10-24 10:04:44 +00:00
Patrick Niklaus 29ce651493 Enable building the 5.13 branch 2017-10-20 15:24:29 +00:00
Patrick Niklaus 1b53b90eec Add missing entry to changelog 2017-10-20 15:08:18 +00:00
Patrick Niklaus 5f84032261 Bump version to RC2 2017-10-20 14:57:08 +00:00
Patrick Niklaus 9c73e42f5f Rename locations-cache -> location-cache 2017-10-20 14:56:10 +00:00
Patrick Niklaus c638499c0f Add changelog entry for changed behavior 2017-10-20 14:56:10 +00:00
Patrick Niklaus 7c5977daf6 Change --use-location-cache=false to --disbale-location-cache 2017-10-20 14:56:10 +00:00
Patrick Niklaus 253522c406 Fix tests 2017-10-20 14:56:10 +00:00
Patrick Niklaus 1e2d3882d1 Replace use of implicit_value since that broke with boost 1.65 2017-10-20 14:56:10 +00:00
Patrick Niklaus fd43586b60 Update package-lock 2017-10-18 15:02:51 +00:00
Patrick Niklaus fd13ffe7ba Version bump for RC1 2017-10-17 14:11:27 +00:00
101 changed files with 814 additions and 4059 deletions
-2
View File
@@ -1,2 +0,0 @@
test
build
+2 -50
View File
@@ -13,9 +13,9 @@ notifications:
branches:
only:
- master
- "5.13"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
- 5.14
cache:
yarn: true
@@ -286,54 +286,6 @@ matrix:
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-8-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="8"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-6-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="8"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
before_install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
@@ -423,7 +375,7 @@ install:
script:
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
- make -C test/data benchmark
- ./example/build/osrm-example test/data/mld/monaco.osrm
- ./example/build/osrm-example test/data/ch/monaco.osrm
# All tests assume to be run from the build directory
- pushd ${OSRM_BUILD_DIR}
- ./unit_tests/library-tests
+1 -41
View File
@@ -1,44 +1,4 @@
# 5.14.2
- Changes from 5.14.1:
- Bugfixes:
- FIXED #4727: Erroring when a old .core file is present.
- FIXED #4642: Update checks for EMPTY_NAMEID to check for empty name strings
- FIXED #4738: Fix potential segmentation fault
# 5.14.1
- Changes from 5.14.0
- Bugfixes:
- FIXED: don't use removed alternative candidates in `filterPackedPathsByCellSharing`
# 5.14.0
- Changes from 5.13
- API:
- ADDED: new RouteStep property `driving_side` that has either "left" or "right" for that step
- Misc:
- ADDED: Bundles a rough (please improve!) driving-side GeoJSON file for use with `osrm-extract --location-dependent-data data/driving_side.geojson`
- CHANGED: Conditional turn parsing is disabled by default now
- ADDED: Adds a tool to analyze turn instruction generation in a dataset. Useful for tracking turn-by-turn heuristic changes over time.
- CHANGED: Internal refactoring of guidance code as a first step towards a re-runnable guidance pipeline
- ADDED: Now publishing Node 8.x LTS binary modules
- Profile:
- CHANGED: Remove dependency on turn types and turn modifier in the process_turn function in the `car.lua` profile. Guidance instruction types are not used to influence turn penalty anymore so this will break backward compatibility between profile version 3 and 4.
- Guidance:
- ADDED: New internal flag on "segregated intersections" - in the future, will should allow collapsing of instructions across complex intersection geometry where humans only perceive a single maneuver
- CHANGED: Decrease roundabout turn radius threshold from 25m to 15m - adds some "exit the roundabout" instructions for moderately sized roundabouts that were being missed previously
- Docker:
- CHANGED: switch to alpine 3.6, and use a multistage build to reduce image size
- Build:
- FIX: use LUA_LIBRARY_DIRS to propertly detect Lua on all platforms
- Docs:
- FIX: clarify description of roundabout exit instructions
- Bugfixes:
- FIXED: Fix bug where merge instructions got the wrong direction modifier ([PR #4670](https://github.com/Project-OSRM/osrm-backend/pull/4670))
- FIXED: Properly use the `profile.properties.left_hand_driving` property, there was a typo that meant it had no effect
- FIXED: undefined behaviour when alternative candidate via node is same as source node ([#4691](https://github.com/Project-OSRM/osrm-backend/issues/4691))
- FIXED: ensure libosrm.pc is pushed to the correct location for pkgconfig to find it on all platforms
- FIXED: don't consider empty names + empty refs as a valid name for u-turns
# 5.13.0
# 5.13.0 RC4
- Changes from 5.12:
- Profile:
- Append cardinal directions from route relations to ref fields to improve instructions; off by default see `profile.cardinal_directions`
+3 -3
View File
@@ -61,8 +61,8 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 14)
set(OSRM_VERSION_PATCH 2)
set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
@@ -796,7 +796,7 @@ JOIN("-I${DEPENDENCIES_INCLUDE_DIRS}" " -I" PKGCONFIG_OSRM_INCLUDE_FLAGS)
JOIN("${ENGINE_LIBRARIES}" " " PKGCONFIG_OSRM_DEPENDENT_LIBRARIES)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION ${PKGCONFIG_LIBRARY_DIR}/pkgconfig)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# uninstall target
configure_file(
-3
View File
@@ -1,3 +0,0 @@
# Code of conduct
Everyone is invited to participate in Project OSRMs open source projects and public discussions: we want to create a welcoming and friendly environment. Harassment of participants or other unethical and unprofessional behavior will not be tolerated in our spaces. The [Contributor Covenant](http://contributor-covenant.org) applies to all projects under the Project-OSRM organization and we ask that you please read [the full text](http://contributor-covenant.org/version/1/2/0/).
+1 -5
View File
@@ -1,12 +1,8 @@
# Everyone
Please take some time to review our [code of conduct](CODE-OF-CONDUCT.md) to help guide your interactions with others on this project.
# User
Before you open a new issue, please search for older ones that cover the same issue.
In general "me too" comments/issues are frowned upon.
You can add a :+1: emoji reaction to the issue if you want to express interest in this.
You can add a :+1: emoji to the issue if you want to express interest in this.
# Developer
+1
View File
@@ -19,6 +19,7 @@ To quickly try OSRM use our [demo server](http://map.project-osrm.org) which com
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [this guide about mapping for navigation](https://www.mapbox.com/mapping/mapping-for-navigation/).
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
- [node-osrm](https://www.npmjs.com/package/osrm) - Production-ready NodeJs bindings for the routing engine
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
- [osrm-text-instructions](https://github.com/Project-OSRM/osrm-text-instructions) - Text instructions from OSRM route response
- [osrm-backend-docker](https://hub.docker.com/r/osrm/osrm-backend/) - Ready to use Docker images
-5
View File
@@ -84,15 +84,11 @@ function(_lua_set_version_vars)
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
pkg_check_modules(LUA QUIET "lua${ver}")
list(APPEND _lua_include_subdirs ${LUA_INCLUDE_DIRS})
list(APPEND _lua_library_names ${LUA_LIBRARIES})
list(APPEND _lua_library_dirs ${LUA_LIBRARY_DIRS})
endforeach ()
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
set(_lua_library_names "${_lua_library_names}" PARENT_SCOPE)
set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
set(_lua_library_dirs "${_lua_library_dirs}" PARENT_SCOPE)
endfunction(_lua_set_version_vars)
function(_lua_check_header_version _hdr_file)
@@ -165,7 +161,6 @@ find_library(LUA_LIBRARY
ENV LUA_DIR
PATH_SUFFIXES lib
PATHS
${_lua_library_dirs}
~/Library/Frameworks
/Library/Frameworks
/sw
+2 -2
View File
@@ -1,6 +1,6 @@
module.exports = {
default: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only --require features/support --require features/step_definitions',
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -f progress --require features/support --require features/step_definitions',
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
File diff suppressed because it is too large Load Diff
+28 -20
View File
@@ -1,20 +1,34 @@
FROM alpine:3.6 as buildstage
FROM alpine:3.5
ARG DOCKER_TAG
RUN mkdir -p /src && mkdir -p /opt
COPY . /src
WORKDIR /src
RUN mkdir /opt
WORKDIR /opt
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk upgrade && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
\
echo "Building libstxxl" && \
cd /opt && \
git clone --depth 1 --branch 1.4.1 https://github.com/stxxl/stxxl.git && \
cd stxxl && \
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Release .. && \
make -j${NPROC} && \
make install
ARG DOCKER_TAG
RUN mkdir /src
COPY . /src
WORKDIR /src
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "Building OSRM ${DOCKER_TAG}" && \
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
mkdir -p build && \
mkdir build && \
cd build && \
BUILD_TYPE="Release" && \
ENABLE_ASSERTIONS="Off" && \
@@ -27,19 +41,13 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
cd ../profiles && \
cp -r * /opt && \
\
echo "Cleaning up" && \
strip /usr/local/bin/* && \
rm -rf /src /usr/local/lib/libosrm*
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
FROM alpine:3.6 as runstage
RUN mkdir -p /src && mkdir -p /opt
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat libtbb@testing
COPY --from=buildstage /usr/local /usr/local
COPY --from=buildstage /opt /opt
WORKDIR /opt
rm /usr/local/lib/libstxxl* && \
cd /opt && \
apk del boost-dev && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.2-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat && \
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
EXPOSE 5000
+1 -2
View File
@@ -594,7 +594,6 @@ step.
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
- `rotary_pronunciation`: The pronunciation hint of the rotary name. Optionally included, if the step is a rotary and a rotary pronunciation is available.
- `driving_side`: The legal driving side at the location for this step. Either `left` or `right`.
#### Example
@@ -665,7 +664,7 @@ step.
| `end of road` | road ends in a T intersection turn in direction of `modifier`|
| `use lane` | **Deprecated** replaced by lanes on all intersection entries |
| `continue` | Turn in direction of `modifier` to stay on the same road |
| `roundabout` | traverse roundabout, if the route leaves the roundabout there will be an additional property `exit` for exit counting. The modifier specifies the direction of entering the roundabout. |
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
+38 -37
View File
@@ -6,7 +6,7 @@ OSRM supports "profiles". Profiles representing routing behavior for different t
## Available profiles
Out-of-the-box OSRM comes with profiles for car, bicycle and foot. You can easily modify these or create new ones if you like.
Profiles have a 'lua' extension, and are placed in 'profiles' directory.
Profiles have a 'lua' extension, and are places in 'profiles' directory.
When running OSRM preprocessing commands you specify the profile with the --profile (or the shorthand -p) option, for example:
@@ -17,8 +17,8 @@ It's important to understand that profiles are used when preprocessing the OSM d
This means that after modifying a profile **you will need to extract, contract and reload the data again** and to see changes in the routing results. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow) for more.
## Profiles are written in Lua
Profiles are not just configuration files. They are scripts written in the [Lua scripting language](http://www.lua.org). The reason for this is that OpenStreetMap data is complex, and it's not possible to simply define tag mappings. Lua scripting offers a powerful way to handle all the possible tag combinations found in OpenStreetMap nodes and ways.
## Profiles are written in LUA
Profiles are not just configuration files. They are scripts written in the [LUA scripting language](http://www.lua.org). The reason for this is that OpenStreetMap data is complex, and it's not possible to simply define tag mappings. LUA scripting offers a powerful way to handle all the possible tag combinations found in OpenStreetMap nodes and ways.
## Basic structure of profiles
A profile will process every node and way in the OSM input data to determine what ways are routable in which direction, at what speed, etc.
@@ -35,40 +35,40 @@ A profile can also define various local functions it needs.
Looking at [car.lua](../profiles/car.lua) as an example, at the top of the file the api version is defined and then required library files are included.
Then follows the `setup` function, which is called once when the profile is loaded. It returns a big hash table of configurations, specifying things like what speed to use for different way types. The configurations are used later in the various processing functions. Many adjustments can be done just by modifying this configuration table.
Then follows the `setup` functions, which is called once when the profile is loaded. It returns a big hash table of configurations, specifying things like what speed to use for different way types. The configurations are used later in the various processing functions. Many adjustments can be done just be modifying this configuration table.
The setup function is also where you can do other setup, like loading an elevation data source if you want to consider that when processing ways.
The setup function is also where you can do other setup, like loading elevation data source if you want to consider that when processing ways.
Then come the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`.
Then comes the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`.
The `process_turn` function processes every possible turn in the network, and sets a penalty depending on the angle and turn of the movement.
Profiles can also define a `process_segment` function to handle differences in speed along an OSM way, for example to handle elevation. As you can see, this is not currently used in the car profile.
At the end of the file, a table is returned with references to the setup and processing functions the profile has defined.
At the end of the file, a table if returned with references to the setup and processing functions the profile has defined.
## Understanding speed, weight and rate
When computing a route from A to B there can be different measures of what is the best route. That's why there's a need for different profiles.
When computing a route from A to B there can be different measure of what is the best route. That's why there's a need for different profiles.
Because speeds vary on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer.
Because speeds very on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer.
To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concepts of `weight` and `rate`. The rate is an abstract measure that you can assign to ways as you like to make some ways preferable to others. Routing will prefer ways with high rate.
To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concept of `weight` and `rate`. The rate is an abstract measure that you can assign to ways as you like to make some ways preferable to others. Routing will prefer ways with high rate.
The weight of a way is normally computed as length / rate. The weight can be thought of as the resistance or cost when passing the way. Routing will prefer ways with low weight.
The weight of a way normally computed as length / rate. The weight can be thought of as the resistance or cost when passing the way. Routing will prefer ways with low weight.
You can also set the weight of a way to a fixed value. In this case it's not calculated based on the length or rate, and the rate is ignored.
You can also set the weight of a way to a fixed value, In this case it's not calculated based on the length or rate, and the rate is ignored.
You should set the speed to your best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times.
You should set the speed to you best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times.
If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time estimation will be skewed.
If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time time estimation will be skewed.
If you set the same rate on all ways, the result will be shortest path routing.
If you set rate = speed on all ways, the result will be fastest path routing.
If you want to prioritize certain streets, increase the rate on these.
If you want to prioritize certain street, increase the rate on these.
## Elements
### api_version
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
A profile should set api_version at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If api_version is not defined, 0 will be assumed. The current api version is 2.
### Library files
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
@@ -81,15 +81,15 @@ set.lua | Defines the Set helper for handling sets of values
sequence.lua | Defines the Sequence helper for handling sequences of values
access.lua | Function for finding relevant access tags
destination.lua | Function for finding relevant destination tags
maxspeed.lua | Function for determining maximum speed
destination.lua | Function for determining maximum speed
guidance.lua | Function for processing guidance attributes
They all return a table of functions when you use `require` to load them. You can either store this table and reference its functions later, or if you need only a single function you can store that directly.
They all return a table of functions when you use `require` to load them. You can either store this table and reference it's functions later, of if you need only a single you can store that directly.
### setup()
The `setup` function is called once when the profile is loaded and must return a table of configurations. It's also where you can do other global setup, like loading data sources that are used during processing.
Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA iinterpreter will have its own set of globals.
Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA iinterpreter will have it's own set of globals.
The following global properties can be set under `properties` in the hash you return in the `setup` function:
@@ -109,7 +109,8 @@ The following additional global properties can be set in the hash you return in
Attribute | Type | Notes
-------------------------------------|------------------|----------------------------------------------------------------------------
excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time. E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways.
excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time.
| | E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways.
classes | Sequence | Determines the allowed classes that can be referenced using `{forward,backward}_classes` on the way in the `process_way` function.
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
@@ -146,26 +147,26 @@ Importantly it will set `result.forward_mode` and `result.backward_mode` to indi
It will also set a number of other attributes on `result`.
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `process_way` function. Instead `process_way` will examine the tag set on the way, process this information in various ways, calling other local functions and referencing the configuration in `profile`, etc., before arriving at the result.
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `process_way` function. Instead `process_way` will examine the tag set on the way, process this information in various ways, calling other local functions and referencing the configuration in `profile`, etc, before arriving at the result.
The following attributes can be set on the result in `process_way`:
Attribute | Type | Notes
----------------------------------------|----------|--------------------------------------------------------------------------
forward_speed | Float | Speed on this way in km/h. Mandatory.
backward_speed | Float | ""
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 | ""
backward_rate | Float | " "
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
backward_mode | Enum | ""
backward_mode | Enum | " "
forward_classes | Table | Mark this way as being of a specific class, e.g. `result.classes["toll"] = true`. This will be exposed in the API as `classes` on each `RouteStep`.
backward_classes | Table | ""
backward_classes | Table | " "
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 (normalized OSM `turn:lanes` value)
turn_lanes_backward | String | ""
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 | ""
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?
@@ -187,18 +188,18 @@ The `process_segment` function is called for every segment of OSM ways. A segmen
On OpenStreetMap way cannot have different tags on different parts of a way. Instead you would split the way into several smaller ways. However many ways are long. For example, many ways pass hills without any change in tags.
Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment accordingly.
Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment.
In the `process_segment` function you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to look up information from another data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example.
In the `process_segment` you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to lookup other data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example.
The following attributes can be read and set on the result in `process_segment`:
Attribute | Read/write? | Type | Notes
-------------------|-------------|---------|----------------------------------------
source.lon | Read | Float | Co-ordinates of segment start
source.lat | Read | Float | ""
source.lat | Read | Float | " "
target.lon | Read | Float | Co-ordinates of segment end
target.lat | Read | Float | ""
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
@@ -230,7 +231,7 @@ The priority-category influences the decision which road is considered the obvio
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
### Using raster data
OSRM has built-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes.
OSRM has build-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes.
Use `raster:load()` in your `setup` function to load data and store the source in your configuration hash:
@@ -283,8 +284,8 @@ See [rasterbot.lua](../profiles/rasterbot.lua) and [rasterbotinterp.lua](../prof
### Helper functions
There are a few helper functions defined in the global scope that profiles can use:
- `durationIsValid`
- `parseDuration`
- `trimLaneString`
- `applyAccessTokens`
- `canonicalizeStringList`
durationIsValid
parseDuration
trimLaneString
applyAccessTokens
canonicalizeStringList
-8
View File
@@ -30,17 +30,9 @@ int main(int argc, const char *argv[])
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
EngineConfig config;
config.storage_config = {argv[1]};
config.use_shared_memory = false;
// We support two routing speed up techniques:
// - Contraction Hierarchies (CH): requires extract+contract pre-processing
// - Multi-Level Dijkstra (MLD): requires extract+partition+customize pre-processing
//
// config.algorithm = EngineConfig::Algorithm::CH;
config.algorithm = EngineConfig::Algorithm::MLD;
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
const OSRM osrm{config};
-1
View File
@@ -10,7 +10,6 @@ Feature: Barriers
| | x |
| bollard | x |
| gate | x |
| lift_gate | x |
| cycle_barrier | x |
| cattle_grid | x |
| border_control | x |
+10 -10
View File
@@ -20,9 +20,9 @@ Feature: Car - Handle driving
| efg | primary | | |
When I route I should get
| from | to | route | modes | turns |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | depart,new name right,new name left,arrive |
| e | a | cde,abc,abc | driving,driving,driving | depart,new name left,arrive |
| from | to | route | modes |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving |
| e | a | cde,abc,abc | driving,driving,driving |
Scenario: Car - Control test without durations, osrm uses movable bridge speed to calculate duration
Given the node map
@@ -39,9 +39,9 @@ Feature: Car - Handle driving
| efg | primary | |
When I route I should get
| from | to | route | modes | speed | time | turns |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 332s +-1 | depart,new name right,new name left,arrive |
| e | c | cde,cde | driving,driving | 5 km/h | 288s +-1 | depart,arrive |
| from | to | route | modes | speed | time |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 340s +-1 |
| e | c | cde,cde | driving,driving | 5 km/h | 295s +-1 |
Scenario: Car - Properly handle durations
Given the node map
@@ -58,7 +58,7 @@ Feature: Car - Handle driving
| efg | primary | | |
When I route I should get
| from | to | route | modes | speed | turns |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h | depart,new name right,new name left,arrive |
| c | e | cde,cde | driving,driving | 2 km/h | depart,arrive |
| e | c | cde,cde | driving,driving | 2 km/h | depart,arrive |
| from | to | route | modes | speed |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
| c | e | cde,cde | driving,driving | 2 km/h |
| e | c | cde,cde | driving,driving | 2 km/h |
+20 -45
View File
@@ -4,7 +4,7 @@ Feature: Testbot - side bias
Scenario: Left-hand bias
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
profile.left_hand_driving = true
profile.turn_bias = 1.075
"""
And the node map
@@ -20,14 +20,14 @@ Feature: Testbot - side bias
| bd |
When I route I should get
| from | to | route | time | driving_side |
| d | a | bd,ab,ab | 24s +-1 | left,left,left |
| d | c | bd,bc,bc | 27s +-1 | left,left,left |
| from | to | route | time |
| d | a | bd,ab,ab | 24s +-1 |
| d | c | bd,bc,bc | 27s +-1 |
Scenario: Right-hand bias
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
profile.left_hand_driving = true
profile.turn_bias = 1 / 1.075
"""
And the node map
@@ -43,14 +43,14 @@ Feature: Testbot - side bias
| bd |
When I route I should get
| from | to | route | time | driving_side | # |
| d | a | bd,ab,ab | 27s +-1 | left,left,left | should be inverse of left hand bias |
| d | c | bd,bc,bc | 24s +-1 | left,left,left | |
| from | to | route | time | # |
| d | a | bd,ab,ab | 27s +-1 | should be inverse of left hand bias |
| d | c | bd,bc,bc | 24s +-1 | |
Scenario: Roundabout exit counting for left sided driving
Given the profile file "car" initialized with
Given the profile file "testbot" initialized with
"""
profile.properties.left_hand_driving = true
profile.left_hand_driving = true
"""
And a grid size of 10 meters
And the node map
@@ -70,10 +70,10 @@ Feature: Testbot - side bias
| bcegb | roundabout |
When I route I should get
| waypoints | route | driving_side | turns |
| a,d | ab,cd,cd | left,left,left | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | left,left,left | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | left,left,left | depart,roundabout turn right exit-3,arrive |
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
Scenario: Left-hand bias via location-dependent tags
@@ -92,9 +92,9 @@ Feature: Testbot - side bias
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | driving_side | time |
| d | a | bd,ab,ab | left,left,left | 24s +-1 |
| d | c | bd,bc,bc | left,left,left | 27s +-1 |
| from | to | route | time |
| d | a | bd,ab,ab | 24s +-1 |
| d | c | bd,bc,bc | 27s +-1 |
Scenario: Left-hand bias via OSM tags
@@ -113,31 +113,6 @@ Feature: Testbot - side bias
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | driving_side | time |
| d | a | bd,ab,ab | right,right,right | 27s +-1 |
| d | c | bd,bc,bc | right,right,right | 24s +-1 |
Scenario: changing sides
Given the profile "car"
# Note - the boundary in null-island.geojson is at lon = 2.0,
# and we use the "last node of the way" as the heuristic to detect
# whether the way is in our out of the driving_side polygon
And the node locations
| node | lat | lon |
| a | 0 | 0.5 |
| b | 0 | 1.5 |
| c | 0 | 2.5 |
| d | 0 | 3.5 |
And the ways
| nodes |
| ab |
| bc |
| cd |
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | driving_side |
| d | a | cd,bc,ab,ab | right,right,left,left |
| a | d | ab,bc,cd,cd | left,right,right,right |
| from | to | route | time |
| d | a | bd,ab,ab | 27s +-1 |
| d | c | bd,bc,bc | 24s +-1 |
+5 -5
View File
@@ -6,9 +6,9 @@ Feature: Car - weights
And the node map
"""
a--b--c
| |
d |
| |
|
d
|
e--f--g
"""
And the ways
@@ -19,7 +19,7 @@ Feature: Car - weights
| bdf | service |
When I route I should get
| from | to | route | speed | weight |
| a | e | abc,cg,efg,efg | 29 km/h | 122.4 |
| a | e | abc,cg,efg,efg | 28 km/h | 126.6 |
| a | d | abc,bdf,bdf | 18 km/h | 71.7 |
Scenario: Does not jump off the highway to go down service road
@@ -59,7 +59,7 @@ Feature: Car - weights
When I route I should get
| from | to | route | speed | weight |
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
| a | e | ab,be,be | 14 km/h | 111.8 |
| a | e | ab,be,be | 14 km/h | 112 |
Scenario: Distance weights
Given the profile file "car" initialized with
-1
View File
@@ -10,7 +10,6 @@ Feature: Barriers
| | x |
| bollard | x |
| gate | x |
| lift_gate | x |
| cycle_barrier | x |
| cattle_grid | x |
| border_control | x |
+1 -1
View File
@@ -47,7 +47,7 @@ Feature: Turn Lane Guidance
e
a . . b . . . c g
` .
` .
` .
` d
f
"""
-50
View File
@@ -50,32 +50,6 @@ Feature: Collapse
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Segregated Intersection, Cross Belonging to Single Street
Given the node map
"""
g
c b a
d e f
h i
"""
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | first | yes |
| de | primary | first | yes |
| ef | primary | first | yes |
| gb | primary | second | no |
| be | primary | second | no |
| eh | primary | second | yes |
| ei | primary | third | yes |
When I route I should get
| waypoints | route | turns | locations |
| a,i | first,second,third,third | depart,turn left,turn slight left,arrive | a,b,e,i |
Scenario: Segregated Intersection, Cross Belonging to Correct Street
Given the node map
"""
@@ -1100,27 +1074,3 @@ Feature: Collapse
When I route I should get
| waypoints | bearings | route | turns | locations |
| 1,2 | 90 270 | ab,bd,bd,ab,ab | depart,turn left,continue uturn,turn right,arrive | _,b,d,b,_ |
# https://www.openstreetmap.org/#map=18/37.74844/-122.40275
Scenario: Don't use destinations as names
Given the node map
"""
f - - - - e - - - - d
|
|
|
|
|
a - - - - b - - - - c
"""
And the ways
| nodes | highway | name | oneway | destination:ref |
| abc | residential | road | yes | |
| def | motorway_link | | yes | US 101 |
| be | residential | cross | no | |
When I route I should get
| waypoints | route | turns |
| a,f | road,cross,, | depart,turn left,on ramp left,arrive |
+23 -159
View File
@@ -354,9 +354,9 @@ Feature: Merge Segregated Roads
| hb | road | yes |
When I route I should get
| waypoints | turns | route | intersections |
| waypoints | turns | route | intersections |
| a,f | depart,arrive | road,road | true:180,false:0 true:180,false:0 true:180;true:0 |
| c,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| c,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| 1,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| f,a | depart,arrive | road,road | true:0,true:0 false:180,true:0 false:180;true:180 |
| g,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
@@ -518,32 +518,35 @@ Feature: Merge Segregated Roads
# the goal here should be not to mention the intersection in the middle at all and also suppress the segregated parts
When I route I should get
| waypoints | route | intersections |
| waypoints | route | intersections |
| a,l | horiz,vert,vert | true:90;false:0 true:60 true:90 true:180 false:270,true:60 false:120 false:240 false:300,true:0 false:90 false:180 false:240 true:270;true:180 |
| a,d | horiz,horiz | true:90,false:0 true:60 true:90 true:180 false:270,false:0 true:90 false:180 false:270 true:300;true:270 |
| a,d | horiz,horiz | true:90,false:0 true:60 true:90 true:180 false:270,false:0 true:90 false:180 false:270 true:300;true:270 |
| j,h | vert,horiz,horiz | true:0;true:0 true:90 false:180 false:270 true:300,false:60 false:120 false:240 true:300,false:0 false:90 false:120 true:180 true:270;true:90 |
| j,l | vert,vert | true:0,true:0 true:90 false:180 false:270 true:300,true:0 false:90 false:180 true:240 false:270;true:180 |
| j,l | vert,vert | true:0,true:0 true:90 false:180 false:270 true:300,true:0 false:90 false:180 true:240 false:270;true:180 |
Scenario: Square Area - Don't merge almost circular roads
Given a grid size of 2 meters
Given the node map
"""
i
b `
` ` p .
a ` g` ` \ f
\ / o /
\ / \ /
h - - c n /
\ \/
k e
\ /
l /
i
/
/
/
b---- g .
/ p .
a / \ f
\ / o /
\ / \ /
c n /
/ \ \/
/ k e
/ \ /
h l /
\ /
m . d
/
j
/
j
"""
And the ways
@@ -557,144 +560,5 @@ Feature: Merge Segregated Roads
| jd | Hubertusallee | yes |
When I route I should get
| waypoints | route | turns |
| i,h | Kurfürstendamm,Rathenauplatz,Hubertusallee,Hubertusallee | depart,turn right,turn right,arrive |
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
Scenario: Do not merge links between segregated roads
Given the node map
"""
f
`````````` ..............
` ` ` ` e - - - - - - - d
a 1
```````````.............. |
`````````` b - - - - - - - c
|
|
|
|
g
"""
And the ways
| nodes | name | oneway |
| ab | germ | yes |
| bc | ober | yes |
| de | ober | yes |
| ef | germ | yes |
| eb | germ | no |
| gb | germ | no |
When I route I should get
| waypoints | route | turns |
| a,c | germ,ober | depart,arrive |
| a,g | germ,germ,germ | depart,continue right,arrive |
| a,1 | germ,germ,germ | depart,continue left,arrive |
| d,g | ober,germ,germ | depart,turn left,arrive |
# https://www.openstreetmap.org/#map=19/51.32888/6.57059
Scenario: Places in presence of oneways
Given the node map
"""
i l
| |
| |
g - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - f
| |
| |
a - - - b - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - c - - - d
| |
| |
j k
"""
And the ways
| nodes | name | oneway |
| ab | schwert | yes |
| cd | schwert | yes |
| ig | luise | yes |
| bj | luise | yes |
| kc | marianne | yes |
| fl | marianne | yes |
| bc | albrecht | no |
| fg | albrecht | no |
| gb | albrecht | yes |
| cf | albrecht | yes |
When I route I should get
| waypoints | route | turns |
| a,l | schwert,albrecht,marianne,marianne | depart,new name straight,turn left,arrive |
| a,j | schwert,luise,luise | depart,turn right,arrive |
| a,1 | schwert,albrecht,albrecht,albrecht | depart,new name straight,continue uturn,arrive |
| k,l | marianne,marianne | depart,arrive |
| k,j | marianne,albrecht,luise,luise | depart,turn left,turn left,arrive |
| k,d | marianne,schwert,schwert | depart,turn right,arrive |
| i,j | luise,luise | depart,arrive |
| i,d | luise,albrecht,schwert,schwert | depart,turn left,turn straight,arrive |
| i,l | luise,albrecht,marianne,marianne | depart,turn left,turn left,arrive |
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
Scenario: Do not merge links between segregated roads
Given the node map
"""
d
f............... |
`````````` .............. |
a............... ` ` ` ` e
``````````.............. 1
`````````` b
- - - - - - - c
"""
And the ways
| nodes | name | oneway |
| ab | otto | yes |
| bc | otto | no |
| de | neu | no |
| ef | otto | yes |
| eb | otto | no |
When I route I should get
| waypoints | route | turns | # |
| a,c | otto,otto | depart,arrive | |
| a,f | otto,otto,otto | depart,continue uturn,arrive | |
| a,1 | otto,otto,otto | depart,continue left,arrive | |
| a,d | otto,neu,neu | depart,turn left,arrive | |
| c,1 | otto,otto | depart,arrive | |
| c,f | otto,otto,otto | depart,continue left,arrive | Ideally, this would be depart,arrive, but the obvious discovery making the turn onto `1` from `c` obvious interferes here |
# https://www.openstreetmap.org/#map=18/50.94608/7.02030
Scenario: Do not merge oneway places
Given the node map
"""
j
|
|
g - f - - - - - - - e
| |
| |
| d
| \
| .c.
a - - - - - - b` `
| `
| ` h
|
|
i
"""
And the ways
| nodes | name | oneway |
| efabc | kobe | yes |
| edc | kobe | no |
| fg | arn | no |
| ia | kobu | yes |
| hc | wei | no |
| ej | wei | no |
When I route I should get
| waypoints | route | turns |
| j,h | wei,wei | depart,arrive |
| a,d | kobe,kobe,kobe | depart,continue left,arrive |
| waypoints | route | turns |
| i,h | Kurfürstendamm,Hubertusallee,Hubertusallee | depart,turn straight,arrive |
-21
View File
@@ -126,24 +126,3 @@ Feature: Merging
When I route I should get
| waypoints | route | turns |
| d,c | ,A100,A100 | depart,merge slight right,arrive |
# https://www.openstreetmap.org/way/254299122
@merge
Scenario: Merge onto a motorway with junction references
Given the node map
"""
a b c d
e f
"""
And the ways
| nodes | name | junction:ref | highway | oneway |
| abc | A100 | | motorway | yes |
| cd | A100 | 1A | motorway | yes |
| eb | | | motorway_link | yes |
| cf | | 1B | motorway_link | yes |
When I route I should get
| waypoints | route | turns |
| e,d | ,A100,A100 | depart,merge slight left,arrive |
-30
View File
@@ -36,36 +36,6 @@ Feature: Simple Turns
| f,a | depart,arrive | road,road | true:0,true:0 false:150 false:180;true:180 |
| e,a | depart,turn slight right,arrive | turn,road,road | true:333;true:0 false:150 false:180;true:180 |
Scenario: Turning into splitting road - no improvement
Given the node map
"""
a
b
/ |
c d - e
| |
| |
| |
| |
| |
| |
| |
| |
g f
"""
And the ways
| nodes | name | highway | oneway |
| ab | road | primary | no |
| bcg | road | primary | yes |
| fdb | road | primary | yes |
| ed | turn | primary | yes |
When I route I should get
| waypoints | turns | route | intersections |
| f,a | depart,arrive | road,road | true:0,true:0 false:90 false:180;true:180 |
| e,a | depart,turn right,arrive | turn,road,road | true:270;true:0 false:90 false:180;true:180 |
Scenario: Turning into splitting road
Given the node map
"""
@@ -5,7 +5,7 @@ Feature: Basic Roundabout
Given a grid size of 10 meters
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
profile.left_hand_driving = true
"""
Scenario: Roundabout exit counting for left sided driving
+1 -1
View File
@@ -765,7 +765,7 @@ Feature: Basic Roundabout
| e,h | 90 135 | edf,gch,gch,gch | depart,roundabout-exit-2,exit roundabout straight,arrive |
| g,f | 45 90 | gch,edf,edf,edf | depart,roundabout-exit-2,exit roundabout right,arrive |
| g,h | 45 135 | gch,gch,gch | depart,exit roundabout right,arrive |
| e,e | 90 270 | edf,edf,edf | depart,continue uturn,arrive |
| e,e | 90 270 | edf,edf,edf,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
Scenario: CCW and CW roundabouts with overlaps
Given the node map
+3 -66
View File
@@ -972,8 +972,6 @@ Feature: Simple Turns
d
h
q
"""
And the nodes
@@ -983,16 +981,16 @@ Feature: Simple Turns
And the ways
| nodes | name | highway | oneway |
| yf | yf | trunk_link | yes |
| gfehq | Centreville Road | primary | |
| gfeh | Centreville Road | primary | |
| fi | fi | trunk_link | yes |
| ij | Bloomingdale Road | residential | |
| jkabx | Blue Star Memorial Hwy | trunk | yes |
| jkabx | Blue Star Memorial Hwy | trunk | |
| bcde | bcde | trunk_link | yes |
| kh | kh | trunk_link | yes |
When I route I should get
| waypoints | turns | route |
| a,q | depart,off ramp right,turn sharp left,arrive | Blue Star Memorial Hwy,bcde,Centreville Road,Centreville Road |
| a,h | depart,off ramp right,turn sharp left,arrive | Blue Star Memorial Hwy,bcde,Centreville Road,Centreville Road |
@todo
# https://www.openstreetmap.org/#map=20/52.51609/13.41080
@@ -1372,64 +1370,3 @@ Feature: Simple Turns
| waypoints | route | turns |
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
| a,g | ab,befg,befg | depart,fork slight left,arrive |
# https://www.openstreetmap.org/#map=18/52.25130/10.42545
Scenario: Turn for roads with no name, ref changes
Given the node map
"""
d
.
.
e c . . f
.
.
b
.
.
a
"""
And the ways
| nodes | highway | ref | name |
| abc | tertiary | K 57 | |
| cd | tertiary | K 56 | |
| cf | tertiary | K 56 | |
| ce | residential | | Heinrichshöhe |
When I route I should get
| waypoints | route | turns |
| a,f | ,, | depart,turn right,arrive |
# https://www.openstreetmap.org/#map=18/52.24071/10.29066
Scenario: Turn for roads with no name, ref changes
Given the node map
"""
x
.
.
d
. .
. .
. .
e. . t . c . p. .f
. .
. .
. .
b
.
.
a
"""
And the ways
| nodes | highway | ref | name | oneway |
| abp | tertiary | K 23 | | yes |
| pdx | tertiary | K 23 | | yes |
| xdt | tertiary | K 23 | | yes |
| tba | tertiary | K 23 | | yes |
| etcpf | primary | B 1 | | no |
When I route I should get
| waypoints | route | turns |
| e,x | ,,, | depart,turn sharp left,turn right,arrive |
| f,a | ,, | depart,turn left,arrive |
@@ -24,7 +24,7 @@ Feature: Invalid profile API versions
Scenario: Profile API version too high
Given the profile file
"""
api_version = 5
api_version = 4
"""
And the node map
"""
-4
View File
@@ -267,10 +267,6 @@ module.exports = function () {
return this.extractInstructionList(instructions, s => s.mode);
};
this.drivingSideList = (instructions) => {
return this.extractInstructionList(instructions, s => s.driving_side);
};
this.classesList = (instructions) => {
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
};
+1 -7
View File
@@ -35,8 +35,7 @@ module.exports = function () {
if (err) return cb(err);
if (body && body.length) {
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches,
driving_sides;
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
let json = JSON.parse(body);
@@ -54,7 +53,6 @@ module.exports = function () {
turns = this.turnList(json.routes[0]);
intersections = this.intersectionList(json.routes[0]);
modes = this.modeList(json.routes[0]);
driving_sides = this.drivingSideList(json.routes[0]);
classes = this.classesList(json.routes[0]);
times = this.timeList(json.routes[0]);
distances = this.distanceList(json.routes[0]);
@@ -188,10 +186,6 @@ module.exports = function () {
putValue('weight', weight);
putValue('approach', approaches);
if (driving_sides) {
putValue('driving_side', driving_sides);
}
for (var key in row) {
if (this.FuzzyMatch.match(got[key], row[key])) {
got[key] = row[key];
+27 -19
View File
@@ -31,32 +31,40 @@ Feature: Alternative route
| 5 | 6 | dc,ca,ab,bd,dc,dc | |
| 7 | 8 | ca,ab,bd,dc,ca,ca | |
@mld-only
Scenario: Alternative loop paths on a single node with an asymmetric circle
# The test checks only MLD implementation, alternatives results are unpredictable for CH on windows (#4691, #4693)
Given a grid size of 10 meters
# This test case does not work in a platform independent way
# since it depends on a specific CH structure that is only
# present on linux it seems.
@4111 @todo
Scenario: Alternative Loop Paths with single node path
Given the node map
"""
a b c
l d
k e
j f
i h g
a1b2c3d
e f
"""
And the nodes
| node | barrier |
| i | bollard |
| g | bollard |
And the ways
| nodes | oneway |
| abcdefghijkla | no |
| nodes | maxspeed |
| ab | 30 |
| bc | 3 |
| cd | 30 |
| ae | 30 |
| ef | 30 |
| fd | 30 |
And the query options
| alternatives | true |
When I route I should get
| from | to | route | alternative | weight |
| e | k | abcdefghijkla,abcdefghijkla | abcdefghijkla,abcdefghijkla | 6.8 |
| from | to | route | alternative |
| b | c | bc,bc | ab,ae,ef,fd,cd,cd |
#| c | b | bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
| 1 | c | ab,bc,bc | ab,ae,ef,fd,cd,cd |
#| c | 1 | bc,ab | cd,fd,ef,ae,ab | # alternative path depends on phantom snapping order
| 2 | c | bc,bc | |
| c | 2 | bc,bc | |
| 1 | 3 | ab,ae,ef,fd,cd | ab,bc,cd |
#| 3 | 1 | cd,fd,ef,ae,ab | cd,bc,ab | # alternative path depends on phantom snapping order
| b | 3 | bc,cd | ab,ae,ef,fd,cd |
#| 3 | b | cd,bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
@@ -108,7 +108,7 @@ struct ContractedEdgeContainer
edges.insert(edges.end(), new_edges.begin(), new_end);
auto edges_size = edges.size();
auto new_edges_size = std::distance(new_edges.begin(), new_end);
BOOST_ASSERT(static_cast<int>(edges_size) >= new_edges_size);
BOOST_ASSERT(edges_size >= new_edges_size);
flags.resize(edges_size);
std::fill(flags.begin() + edges_size - new_edges_size, flags.end(), flag);
+14
View File
@@ -33,8 +33,22 @@ namespace json
namespace detail
{
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
/**
* Returns a string representing all instruction types (including internal types that
* are normally not exposed in route responses)
*
* @param type the TurnType value to convert into a string
* @return a string representing the turn type (e.g. `turn` or `continue`)
*/
std::string internalInstructionTypeToString(extractor::guidance::TurnType::Enum type);
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
std::string modeToString(const extractor::TravelMode mode);
/**
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
*/
+1 -43
View File
@@ -38,50 +38,8 @@ class NearestAPI final : public BaseAPI
phantom_nodes.front().end(),
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance) {
auto &phantom_node = phantom_with_distance.phantom_node;
auto waypoint = MakeWaypoint(phantom_node);
auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance;
util::json::Array nodes;
std::uint64_t from_node = 0;
std::uint64_t to_node = 0;
std::vector<NodeID> forward_geometry;
if (phantom_node.forward_segment_id.enabled)
{
auto segment_id = phantom_node.forward_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
forward_geometry =
facade.GetUncompressedForwardGeometry(geometry_id);
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry[phantom_node.fwd_segment_position]);
to_node = static_cast<std::uint64_t>(osm_node_id);
}
if (phantom_node.reverse_segment_id.enabled)
{
auto segment_id = phantom_node.reverse_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
std::vector<NodeID> geometry =
facade.GetUncompressedForwardGeometry(geometry_id);
auto osm_node_id = facade.GetOSMNodeIDOfNode(
geometry[phantom_node.fwd_segment_position + 1]);
from_node = static_cast<std::uint64_t>(osm_node_id);
}
else if (phantom_node.forward_segment_id.enabled &&
phantom_node.fwd_segment_position > 0)
{
// In the case of one way, rely on forward segment only
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry[phantom_node.fwd_segment_position - 1]);
from_node = static_cast<std::uint64_t>(osm_node_id);
}
nodes.values.push_back(from_node);
nodes.values.push_back(to_node);
waypoint.values["nodes"] = std::move(nodes);
return waypoint;
});
@@ -885,11 +885,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
// TODO: can be moved to a data block indexed by GeometryID
return edge_based_node_data.IsLeftHandDriving(id);
}
bool IsSegregated(const NodeID id) const override final
{
return edge_based_node_data.IsSegregated(id);
}
};
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
@@ -191,8 +191,6 @@ class BaseDataFacade
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0;
virtual bool IsLeftHandDriving(const NodeID id) const = 0;
virtual bool IsSegregated(const NodeID) const = 0;
};
}
}
+4 -15
View File
@@ -56,7 +56,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
: source_node.forward_segment_id.id;
const auto source_name_id = facade.GetNameIndex(source_node_id);
bool is_segregated = facade.IsSegregated(source_node_id);
const auto source_mode = facade.GetTravelMode(source_node_id);
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
@@ -128,7 +127,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.classes = facade.GetClasses(path_point.classes);
steps.push_back(RouteStep{step_name_id,
is_segregated,
name.to_string(),
ref.to_string(),
pronunciation.to_string(),
@@ -143,18 +141,15 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection},
path_point.is_left_hand_driving});
{intersection}});
if (leg_data_index + 1 < leg_data.size())
{
step_name_id = leg_data[leg_data_index + 1].name_id;
is_segregated = leg_data[leg_data_index + 1].is_segregated;
}
else
{
step_name_id = facade.GetNameIndex(target_node_id);
is_segregated = facade.IsSegregated(target_node_id);
}
// extract bearings
@@ -210,7 +205,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.classes = facade.GetClasses(facade.GetClassData(target_node_id));
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{step_name_id,
is_segregated,
facade.GetNameForID(step_name_id).to_string(),
facade.GetRefForID(step_name_id).to_string(),
facade.GetPronunciationForID(step_name_id).to_string(),
@@ -225,8 +219,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection},
facade.IsLeftHandDriving(target_node_id)});
{intersection}});
}
// In this case the source + target are on the same edge segment
else
@@ -254,7 +247,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const EdgeWeight duration = std::max(0, target_duration - source_duration);
steps.push_back(RouteStep{source_name_id,
is_segregated,
facade.GetNameForID(source_name_id).to_string(),
facade.GetRefForID(source_name_id).to_string(),
facade.GetPronunciationForID(source_name_id).to_string(),
@@ -269,8 +261,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
std::move(maneuver),
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection},
facade.IsLeftHandDriving(source_node_id)});
{intersection}});
}
BOOST_ASSERT(segment_index == number_of_segments - 1);
@@ -296,7 +287,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
BOOST_ASSERT(!leg_geometry.locations.empty());
steps.push_back(RouteStep{target_name_id,
facade.IsSegregated(target_node_id),
facade.GetNameForID(target_name_id).to_string(),
facade.GetRefForID(target_name_id).to_string(),
facade.GetPronunciationForID(target_name_id).to_string(),
@@ -311,8 +301,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
std::move(maneuver),
leg_geometry.locations.size() - 1,
leg_geometry.locations.size(),
{intersection},
facade.IsLeftHandDriving(target_node_id)});
{intersection}});
BOOST_ASSERT(steps.front().intersections.size() == 1);
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
@@ -121,15 +121,9 @@ inline bool haveSameMode(const RouteStep &first, const RouteStep &second, const
// alias for readability
inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
{
const auto has_name_or_ref = [](auto const &step) {
return !step.name.empty() || !step.ref.empty();
};
// make sure empty is not involved
if (!has_name_or_ref(lhs) || !has_name_or_ref(rhs))
{
if (lhs.name_id == EMPTY_NAMEID || rhs.name_id == EMPTY_NAMEID)
return false;
}
// easy check to not go over the strings if not necessary
else if (lhs.name_id == rhs.name_id)
+1 -4
View File
@@ -60,7 +60,6 @@ inline IntermediateIntersection getInvalidIntersection()
struct RouteStep
{
unsigned name_id;
bool is_segregated;
std::string name;
std::string ref;
std::string pronunciation;
@@ -77,7 +76,6 @@ struct RouteStep
std::size_t geometry_begin;
std::size_t geometry_end;
std::vector<IntermediateIntersection> intersections;
bool is_left_hand_driving;
// remove all information from the route step, marking it as invalid (used to indicate empty
// steps to be removed).
@@ -125,13 +123,12 @@ inline void RouteStep::Invalidate()
duration = 0;
distance = 0;
weight = 0;
mode = extractor::TRAVEL_MODE_INACCESSIBLE;
mode = TRAVEL_MODE_INACCESSIBLE;
maneuver = getInvalidStepManeuver();
geometry_begin = 0;
geometry_end = 0;
intersections.clear();
intersections.push_back(getInvalidIntersection());
is_left_hand_driving = false;
}
// Elongate by another step in front
-5
View File
@@ -27,8 +27,6 @@ struct PathData
NodeID turn_via_node;
// name of the street that leads to the turn
unsigned name_id;
// segregated edge-based node that leads to the turn
bool is_segregated;
// weight that is traveled on the segment until the turn is reached
// including the turn weight, if one exists
EdgeWeight weight_until_turn;
@@ -59,9 +57,6 @@ struct PathData
util::guidance::TurnBearing pre_turn_bearing;
// bearing (as seen from the intersection) post-turn
util::guidance::TurnBearing post_turn_bearing;
// Driving side of the turn
bool is_left_hand_driving;
};
struct InternalRouteResult
@@ -164,7 +164,6 @@ void annotatePath(const FacadeT &facade,
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
const auto node_id = *node_from; // edge-based graph node index
const auto name_index = facade.GetNameIndex(node_id);
const bool is_segregated = facade.IsSegregated(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto classes = facade.GetClassData(node_id);
@@ -186,15 +185,12 @@ void annotatePath(const FacadeT &facade,
: 0);
const std::size_t end_index = weight_vector.size();
bool is_left_hand_driving = facade.IsLeftHandDriving(node_id);
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(PathData{id_vector[segment_idx + 1],
name_index,
is_segregated,
weight_vector[segment_idx],
0,
duration_vector[segment_idx],
@@ -206,8 +202,7 @@ void annotatePath(const FacadeT &facade,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0),
is_left_hand_driving});
util::guidance::TurnBearing(0)});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.HasLaneData(turn_id))
@@ -259,7 +254,6 @@ void annotatePath(const FacadeT &facade,
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
bool is_target_left_hand_driving = facade.IsLeftHandDriving(target_node_id);
for (std::size_t segment_idx = start_index; segment_idx != end_index;
(start_index < end_index ? ++segment_idx : --segment_idx))
{
@@ -268,7 +262,6 @@ void annotatePath(const FacadeT &facade,
unpacked_path.push_back(
PathData{id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
facade.GetNameIndex(target_node_id),
facade.IsSegregated(target_node_id),
weight_vector[segment_idx],
0,
duration_vector[segment_idx],
@@ -280,8 +273,7 @@ void annotatePath(const FacadeT &facade,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0),
is_target_left_hand_driving});
util::guidance::TurnBearing(0)});
}
if (unpacked_path.size() > 0)
@@ -75,7 +75,6 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &traffic_lights,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const std::unordered_set<EdgeID> &segregated_edges,
guidance::LaneDescriptionMap &lane_description_map);
void Run(ScriptingEnvironment &scripting_environment,
@@ -158,7 +157,6 @@ class EdgeBasedGraphFactory
const CompressedEdgeContainer &m_compressed_edge_container;
const util::NameTable &name_table;
const std::unordered_set<EdgeID> &segregated_edges;
guidance::LaneDescriptionMap &lane_description_map;
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
+1 -2
View File
@@ -12,8 +12,7 @@ struct EdgeBasedNode
{
GeometryID geometry_id;
ComponentID component_id;
std::uint32_t annotation_id : 31;
std::uint32_t segregated : 1;
AnnotationID annotation_id;
};
} // namespace extractor
+20 -12
View File
@@ -14,33 +14,41 @@ namespace extractor
struct ExtractionTurn
{
ExtractionTurn(double angle,
int number_of_roads,
bool is_u_turn,
ExtractionTurn(const guidance::ConnectedRoad &turn,
bool has_traffic_light,
bool source_restricted,
bool target_restricted,
bool is_left_hand_driving,
TravelMode source_mode,
TravelMode target_mode)
: angle(180. - angle), number_of_roads(number_of_roads), is_u_turn(is_u_turn),
bool is_left_hand_driving)
: angle(180. - turn.angle), turn_type(turn.instruction.type),
direction_modifier(turn.instruction.direction_modifier),
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
weight(0.), duration(0.), source_mode(source_mode), target_mode(target_mode)
weight(0.), duration(0.)
{
}
ExtractionTurn(bool has_traffic_light,
bool source_restricted,
bool target_restricted,
bool is_left_hand_driving)
: angle(0), turn_type(guidance::TurnType::NoTurn),
direction_modifier(guidance::DirectionModifier::Straight),
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
weight(0.), duration(0.)
{
}
const double angle;
const int number_of_roads;
const bool is_u_turn;
const guidance::TurnType::Enum turn_type;
const guidance::DirectionModifier::Enum direction_modifier;
const bool has_traffic_light;
const bool source_restricted;
const bool target_restricted;
const bool is_left_hand_driving;
double weight;
double duration;
TravelMode source_mode;
TravelMode target_mode;
};
}
}
+4 -4
View File
@@ -55,8 +55,8 @@ struct ExtractionWay
turn_lanes_forward.clear();
turn_lanes_backward.clear();
road_classification = guidance::RoadClassification();
forward_travel_mode = extractor::TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = extractor::TRAVEL_MODE_INACCESSIBLE;
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
roundabout = false;
circular = false;
is_startpoint = true;
@@ -112,8 +112,8 @@ struct ExtractionWay
std::string turn_lanes_forward;
std::string turn_lanes_backward;
guidance::RoadClassification road_classification;
extractor::TravelMode forward_travel_mode : 4;
extractor::TravelMode backward_travel_mode : 4;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
// Boolean flags
bool roundabout : 1;
-9
View File
@@ -47,7 +47,6 @@ namespace extractor
class ScriptingEnvironment;
struct ProfileProperties;
class NodeBasedGraphFactory;
class Extractor
{
@@ -72,7 +71,6 @@ class Extractor
const std::unordered_set<NodeID> &traffic_lights,
const std::vector<TurnRestriction> &turn_restrictions,
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
const std::unordered_set<EdgeID> &segregated_edges,
// might have to be updated to add new lane combinations
guidance::LaneDescriptionMap &turn_lane_map,
// for calculating turn penalties
@@ -102,13 +100,6 @@ class Extractor
void WriteConditionalRestrictions(
const std::string &path,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
// Find all "segregated" edges, e.g. edges that can be skipped in turn instructions.
// The main cases are:
// - middle edges between two osm ways in one logic road (U-turn)
// - staggered intersections (X-cross)
// - square/circle intersections
std::unordered_set<EdgeID> FindSegregatedNodes(NodeBasedGraphFactory &factory);
};
}
}
-1
View File
@@ -69,7 +69,6 @@ struct ExtractorConfig final : storage::IOConfig
".osrm.cnbg",
".osrm.cnbg_to_ebg"}),
requested_num_threads(0),
parse_conditionals(false),
use_locations_cache(true)
{
}
+1 -1
View File
@@ -26,7 +26,7 @@ const double constexpr DISTINCTION_RATIO = 2;
const double constexpr MAX_ROUNDABOUT_RADIUS = 15;
// Unnamed small roundabouts that look like intersections are announced as turns,
// guard against data issues or such roundabout intersections getting too large.
const double constexpr MAX_ROUNDABOUT_INTERSECTION_RADIUS = 15;
const double constexpr MAX_ROUNDABOUT_INTERSECTION_RADIUS = 25;
const double constexpr INCREASES_BY_FOURTY_PERCENT = 1.4;
@@ -140,22 +140,6 @@ class MergableRoadDetector
// The detector wants to prevent merges that are connected to `b-e`
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
// The condition suppresses roads merging for intersections like
// . .
// . .
// ---- ----
// . .
// . .
// but will allow roads merging for intersections like
// -------
// / \ 
// ---- ----
// \ /
// -------
bool IsCircularShape(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const;
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const std::vector<util::Coordinate> &node_coordinates;
@@ -165,9 +149,6 @@ class MergableRoadDetector
// name detection
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
// limit for detecting circles / parallel roads
const static double constexpr distance_to_extract = 150;
};
} // namespace guidance
@@ -123,8 +123,7 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
{
SelectStraightmostRoadByNameAndOnlyChoice(const NameID desired_name_id,
const double initial_bearing,
const bool requires_entry,
const bool stop_on_ambiguous_turns);
const bool requires_entry);
/*
* !! REQUIRED - Function for the use of TraverseRoad in the graph walker.
@@ -142,7 +141,6 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
const NameID desired_name_id;
const double initial_bearing;
const bool requires_entry;
const bool stop_on_ambiguous_turns;
};
// find the next intersection given a hop limit
@@ -1,108 +0,0 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_STATISTICS_HANDLER_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_STATISTICS_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/log.hpp"
#include <algorithm>
#include <iomanip>
#include <iterator>
#include <mutex>
#include <unordered_map>
#include <cstdint>
namespace osrm
{
namespace extractor
{
namespace guidance
{
// Unconditionally runs over all intersections and gathers statistics for
// instruction turn types and direction modifiers (see turn_instruction.hpp).
class StatisticsHandler final : public IntersectionHandler
{
public:
StatisticsHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph,
node_data_container,
coordinates,
name_table,
street_name_suffix_table,
intersection_generator)
{
}
~StatisticsHandler() override final
{
const auto add_second = [](const auto acc, const auto &kv) { return acc + kv.second; };
const auto num_types =
std::accumulate(begin(type_hist), end(type_hist), std::uint64_t{0}, add_second);
const auto num_modifiers =
std::accumulate(begin(modifier_hist), end(modifier_hist), std::uint64_t{0}, add_second);
util::Log() << "Assigned " << num_types << " turn instruction types:";
for (const auto &kv : type_hist)
if (kv.second > 0)
util::Log() << std::fixed << std::setprecision(2)
<< internalInstructionTypeToString(kv.first) << ": " << kv.second
<< " (" << (kv.second / static_cast<float>(num_types) * 100.) << "%)";
util::Log() << "Assigned " << num_modifiers << " turn instruction modifiers:";
for (const auto &kv : modifier_hist)
if (kv.second > 0)
util::Log() << std::fixed << std::setprecision(2)
<< instructionModifierToString(kv.first) << ": " << kv.second << " ("
<< (kv.second / static_cast<float>(num_modifiers) * 100.) << "%)";
}
bool canProcess(const NodeID, const EdgeID, const Intersection &) const override final
{
return true;
}
Intersection
operator()(const NodeID, const EdgeID, Intersection intersection) const override final
{
// Lock histograms updates on a per-intersection basis.
std::lock_guard<std::mutex> defer{lock};
// Generate histograms for all roads; this way we will get duplicates
// which we would not get doing it after EBF generation. But we want
// numbers closer to the handlers and see how often handlers ran.
for (const auto &road : intersection)
{
const auto type = road.instruction.type;
const auto modifier = road.instruction.direction_modifier;
type_hist[type] += 1;
modifier_hist[modifier] += 1;
}
return intersection;
}
private:
mutable std::mutex lock;
mutable std::unordered_map<TurnType::Enum, std::uint64_t> type_hist;
mutable std::unordered_map<DirectionModifier::Enum, std::uint64_t> modifier_hist;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_GUIDANCE_VALIDATION_HANDLER_HPP_
@@ -10,7 +10,6 @@
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/sliproad_handler.hpp"
#include "extractor/guidance/statistics_handler.hpp"
#include "extractor/guidance/suppress_mode_handler.hpp"
#include "extractor/guidance/turn_classification.hpp"
#include "extractor/guidance/turn_handler.hpp"
@@ -90,7 +89,6 @@ class TurnAnalysis
const SliproadHandler sliproad_handler;
const SuppressModeHandler suppress_mode_handler;
const DrivewayHandler driveway_handler;
const StatisticsHandler statistics_handler;
// Utility function, setting basic turn types. Prepares for normal turn handling.
Intersection
@@ -309,86 +309,6 @@ inline DirectionModifier::Enum bearingToDirectionModifier(const double bearing)
return extractor::guidance::DirectionModifier::Left;
}
namespace detail
{
const constexpr char *modifier_names[] = {"uturn",
"sharp right",
"right",
"slight right",
"straight",
"slight left",
"left",
"sharp left"};
/**
* Human readable values for TurnType enum values
*/
struct TurnTypeName
{
// String value we return with our API
const char *external_name;
// Internal only string name for the turn type - useful for debugging
// and used by debug tiles for visualizing hidden turn types
const char *internal_name;
};
// Indexes in this list correspond to the Enum values of osrm::extractor::guidance::TurnType
const constexpr TurnTypeName turn_type_names[] = {
{"invalid", "(not set)"},
{"new name", "new name"},
{"continue", "continue"},
{"turn", "turn"},
{"merge", "merge"},
{"on ramp", "on ramp"},
{"off ramp", "off ramp"},
{"fork", "fork"},
{"end of road", "end of road"},
{"notification", "notification"},
{"roundabout", "enter roundabout"},
{"exit roundabout", "enter and exit roundabout"},
{"rotary", "enter rotary"},
{"exit rotary", "enter and exit rotary"},
{"roundabout turn", "enter roundabout turn"},
{"roundabout turn", "enter and exit roundabout turn"},
{"use lane", "use lane"},
{"invalid", "(noturn)"},
{"invalid", "(suppressed)"},
{"roundabout", "roundabout"},
{"exit roundabout", "exit roundabout"},
{"rotary", "rotary"},
{"exit rotary", "exit rotary"},
{"roundabout turn", "roundabout turn"},
{"exit roundabout", "exit roundabout turn"},
{"invalid", "(stay on roundabout)"},
{"invalid", "(sliproad)"}};
} // ns detail
inline std::string instructionTypeToString(const TurnType::Enum type)
{
static_assert(sizeof(detail::turn_type_names) / sizeof(detail::turn_type_names[0]) >=
TurnType::MaxTurnType,
"Some turn types have no string representation.");
return detail::turn_type_names[static_cast<std::size_t>(type)].external_name;
}
inline std::string internalInstructionTypeToString(const TurnType::Enum type)
{
static_assert(sizeof(detail::turn_type_names) / sizeof(detail::turn_type_names[0]) >=
TurnType::MaxTurnType,
"Some turn types have no string representation.");
return detail::turn_type_names[static_cast<std::size_t>(type)].internal_name;
}
inline std::string instructionModifierToString(const DirectionModifier::Enum modifier)
{
static_assert(sizeof(detail::modifier_names) / sizeof(detail::modifier_names[0]) >=
DirectionModifier::MaxDirectionModifier,
"Some direction modifiers have no string representation.");
return detail::modifier_names[static_cast<std::size_t>(modifier)];
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
-10
View File
@@ -71,16 +71,6 @@ struct NodeBasedEdgeAnnotation
std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
std::tie(other.name_id, other.classes, other.travel_mode, other.is_left_hand_driving));
}
bool operator<(const NodeBasedEdgeAnnotation &other) const
{
return (std::tie(name_id, lane_description_id, classes, travel_mode, is_left_hand_driving) <
std::tie(other.name_id,
other.lane_description_id,
other.classes,
other.travel_mode,
other.is_left_hand_driving));
}
};
struct NodeBasedEdge
@@ -41,7 +41,7 @@ class NodeBasedGraphFactory
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
auto const &GetGraph() { return compressed_output_graph; }
auto const &GetGraph() const { return compressed_output_graph; }
auto const &GetBarriers() const { return barriers; }
auto const &GetTrafficSignals() const { return traffic_signals; }
auto &GetCompressedEdges() { return compressed_edge_container; }
@@ -75,7 +75,7 @@ class NodeBasedGraphFactory
// unreferenced entries
void CompressAnnotationData();
// After produce, this will contain a compressed version of the node-based graph
// After produce, this will contain a compresse version of the node-based graph
util::NodeBasedDynamicGraph compressed_output_graph;
// To store the meta-data for the graph that is purely annotative / not used for the navigation
// itself. Since the edges of a node-based graph form the nodes of the edge based graphs, we
+5 -2
View File
@@ -77,8 +77,6 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
return annotation_data[nodes[node_id].annotation_id].is_left_hand_driving;
}
bool IsSegregated(const NodeID node_id) const { return nodes[node_id].segregated; }
NameID GetNameID(const NodeID node_id) const
{
return annotation_data[nodes[node_id].annotation_id].name_id;
@@ -107,8 +105,13 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
// between a large set of nodes
AnnotationID NumberOfAnnotations() const { return annotation_data.size(); }
EdgeBasedNode &GetNode(const NodeID node_id) { return nodes[node_id]; }
EdgeBasedNode const &GetNode(const NodeID node_id) const { return nodes[node_id]; }
NodeBasedEdgeAnnotation &GetAnnotation(const AnnotationID annotation)
{
return annotation_data[annotation];
}
NodeBasedEdgeAnnotation const &GetAnnotation(const AnnotationID annotation) const
{
return annotation_data[annotation];
+3 -4
View File
@@ -21,7 +21,7 @@ struct OriginalEdgeData
LaneDataID lane_data_id,
guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid,
extractor::TravelMode travel_mode,
TravelMode travel_mode,
util::guidance::TurnBearing pre_turn_bearing,
util::guidance::TurnBearing post_turn_bearing)
: via_geometry(via_geometry), name_id(name_id), entry_classid(entry_classid),
@@ -34,8 +34,7 @@ struct OriginalEdgeData
: via_geometry{std::numeric_limits<unsigned>::max() >> 1, false},
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID),
lane_data_id(INVALID_LANE_DATAID), turn_instruction(guidance::TurnInstruction::INVALID()),
travel_mode(extractor::TRAVEL_MODE_INACCESSIBLE), pre_turn_bearing(0.0),
post_turn_bearing(0.0)
travel_mode(TRAVEL_MODE_INACCESSIBLE), pre_turn_bearing(0.0), post_turn_bearing(0.0)
{
}
@@ -44,7 +43,7 @@ struct OriginalEdgeData
EntryClassID entry_classid;
LaneDataID lane_data_id;
guidance::TurnInstruction turn_instruction;
extractor::TravelMode travel_mode;
TravelMode travel_mode;
util::guidance::TurnBearing pre_turn_bearing;
util::guidance::TurnBearing post_turn_bearing;
};
@@ -68,7 +68,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
{
public:
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
static const constexpr int SUPPORTED_MAX_API_VERSION = 4;
static const constexpr int SUPPORTED_MAX_API_VERSION = 3;
explicit Sol2ScriptingEnvironment(
const std::string &file_name,
+2 -53
View File
@@ -29,7 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define TRAVEL_MODE_HPP
#include <cstdint>
#include <string>
namespace osrm
{
@@ -39,6 +38,8 @@ namespace extractor
// This is a char instead of a typed enum, so that we can
// pack it into e.g. a "TravelMode mode : 4" packed bitfield
using TravelMode = std::uint8_t;
}
}
const constexpr osrm::extractor::TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
const constexpr osrm::extractor::TravelMode TRAVEL_MODE_DRIVING = 1;
@@ -54,56 +55,4 @@ const constexpr osrm::extractor::TravelMode TRAVEL_MODE_RIVER_UP = 10;
const constexpr osrm::extractor::TravelMode TRAVEL_MODE_RIVER_DOWN = 11;
const constexpr osrm::extractor::TravelMode TRAVEL_MODE_ROUTE = 12;
// FIXME this actually needs to be configurable from the profiles
inline std::string travelModeToString(const TravelMode mode)
{
std::string token;
switch (mode)
{
case TRAVEL_MODE_INACCESSIBLE:
token = "inaccessible";
break;
case TRAVEL_MODE_DRIVING:
token = "driving";
break;
case TRAVEL_MODE_CYCLING:
token = "cycling";
break;
case TRAVEL_MODE_WALKING:
token = "walking";
break;
case TRAVEL_MODE_FERRY:
token = "ferry";
break;
case TRAVEL_MODE_TRAIN:
token = "train";
break;
case TRAVEL_MODE_PUSHING_BIKE:
token = "pushing bike";
break;
case TRAVEL_MODE_STEPS_UP:
token = "steps up";
break;
case TRAVEL_MODE_STEPS_DOWN:
token = "steps down";
break;
case TRAVEL_MODE_RIVER_UP:
token = "river upstream";
break;
case TRAVEL_MODE_RIVER_DOWN:
token = "river downstream";
break;
case TRAVEL_MODE_ROUTE:
token = "route";
break;
default:
token = "other";
break;
}
return token;
}
} // ns extractor
} // ns osrm
#endif /* TRAVEL_MODE_HPP */
+25 -1
View File
@@ -48,6 +48,14 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"HSGR_CHECKSUM",
"TIMESTAMP",
"FILE_INDEX_PATH",
"CH_CORE_MARKER_0",
"CH_CORE_MARKER_1",
"CH_CORE_MARKER_2",
"CH_CORE_MARKER_3",
"CH_CORE_MARKER_4",
"CH_CORE_MARKER_5",
"CH_CORE_MARKER_6",
"CH_CORE_MARKER_7",
"DATASOURCES_NAMES",
"PROPERTIES",
"BEARING_CLASSID",
@@ -124,6 +132,14 @@ struct DataLayout
HSGR_CHECKSUM,
TIMESTAMP,
FILE_INDEX_PATH,
CH_CORE_MARKER_0,
CH_CORE_MARKER_1,
CH_CORE_MARKER_2,
CH_CORE_MARKER_3,
CH_CORE_MARKER_4,
CH_CORE_MARKER_5,
CH_CORE_MARKER_6,
CH_CORE_MARKER_7,
DATASOURCES_NAMES,
PROPERTIES,
BEARING_CLASSID,
@@ -184,7 +200,15 @@ struct DataLayout
inline uint64_t GetBlockEntries(BlockID bid) const { return num_entries[bid]; }
inline uint64_t GetBlockSize(BlockID bid) const { return num_entries[bid] * entry_size[bid]; }
inline uint64_t GetBlockSize(BlockID bid) const
{
// special bit encoding
if (bid >= CH_CORE_MARKER_0 && bid <= CH_CORE_MARKER_7)
{
return (num_entries[bid] / 32 + 1) * entry_size[bid];
}
return num_entries[bid] * entry_size[bid];
}
inline uint64_t GetSizeOfLayout() const
{
+1
View File
@@ -64,6 +64,7 @@ struct StorageConfig final : IOConfig
{".osrm.hsgr",
".osrm.nbg_nodes",
".osrm.ebg_nodes",
".osrm.core",
".osrm.cells",
".osrm.cell_metrics",
".osrm.mldgr",
+16 -14
View File
@@ -44,20 +44,22 @@ namespace updater
struct UpdaterConfig final : storage::IOConfig
{
UpdaterConfig()
: IOConfig({".osrm.ebg",
".osrm.turn_weight_penalties",
".osrm.turn_duration_penalties",
".osrm.turn_penalties_index",
".osrm.nbg_nodes",
".osrm.ebg_nodes",
".osrm.edges",
".osrm.geometry",
".osrm.fileIndex",
".osrm.properties",
".osrm.restrictions"},
{},
{".osrm.datasource_names"}),
valid_now(0)
: IOConfig(
{
".osrm.ebg",
".osrm.turn_weight_penalties",
".osrm.turn_duration_penalties",
".osrm.turn_penalties_index",
".osrm.nbg_nodes",
".osrm.ebg_nodes",
".osrm.edges",
".osrm.geometry",
".osrm.fileIndex",
".osrm.properties",
".osrm.restrictions",
},
{},
{".osrm.datasource_names"})
{
}
-1
View File
@@ -22,7 +22,6 @@ namespace util
namespace guidance
{
inline void print(const engine::guidance::RouteStep &step)
{
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
+3 -8
View File
@@ -115,7 +115,7 @@ template <typename EdgeDataT> class DynamicGraph
number_of_nodes = nodes;
number_of_edges = static_cast<EdgeIterator>(graph.size());
node_array.resize(number_of_nodes);
node_array.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (const auto node : irange(0u, number_of_nodes))
@@ -129,6 +129,7 @@ template <typename EdgeDataT> class DynamicGraph
node_array[node].edges = edge - last_edge;
position += node_array[node].edges;
}
node_array.back().first_edge = position;
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
edge_list.resize(position);
edge = 0;
@@ -143,8 +144,6 @@ template <typename EdgeDataT> class DynamicGraph
++edge;
}
}
BOOST_ASSERT(node_array.size() == number_of_nodes);
}
// Copy&move for the same data
@@ -192,8 +191,6 @@ template <typename EdgeDataT> class DynamicGraph
// Removes all edges to and from nodes for which filter(node_id) returns false
template <typename Pred> auto Filter(Pred filter) const &
{
BOOST_ASSERT(node_array.size() == number_of_nodes);
DynamicGraph other;
other.number_of_nodes = number_of_nodes;
@@ -205,8 +202,6 @@ template <typename EdgeDataT> class DynamicGraph
std::transform(
node_array.begin(), node_array.end(), other.node_array.begin(), [&](const Node &node) {
const EdgeIterator first_edge = other.edge_list.size();
BOOST_ASSERT(node_id < number_of_nodes);
if (filter(node_id++))
{
std::copy_if(edge_list.begin() + node.first_edge,
@@ -421,7 +416,7 @@ template <typename EdgeDataT> class DynamicGraph
void Renumber(const std::vector<NodeID> &old_to_new_node)
{
// permutate everything but the sentinel
util::inplacePermutation(node_array.begin(), node_array.end(), old_to_new_node);
util::inplacePermutation(node_array.begin(), std::prev(node_array.end()), old_to_new_node);
// Build up edge permutation
auto new_edge_index = 0;
-3
View File
@@ -2,7 +2,6 @@
#define OSRM_GEOJSON_DEBUG_LOGGER_HPP
#include <fstream>
#include <iomanip>
#include <mutex>
#include <string>
@@ -106,8 +105,6 @@ class GeojsonLogger
std::lock_guard<std::mutex> guard(lock);
ofs.open(logfile, std::ios::binary);
ofs << std::setprecision(12);
// set up a feature collection
ofs << "{\n\t\"type\": \"FeatureCollection\",\n\t\"features\": [\n\t";
// remember whether we need to output a colon
+94 -94
View File
@@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.13.0-latest.1",
"version": "5.13.0-rc.1",
"lockfileVersion": 1,
"dependencies": {
"abbrev": {
@@ -372,9 +372,9 @@
"dev": true
},
"chalk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
"integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz",
"integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==",
"dev": true
},
"debug": {
@@ -390,9 +390,9 @@
"dev": true
},
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
},
"to-fast-properties": {
@@ -1088,9 +1088,9 @@
}
},
"browserify-aes": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.8.tgz",
"integrity": "sha512-WYCMOT/PtGTlpOKFht0YJFYcPy6pLCR98CtWfzK13zoynLlBMvAdEMSRGmgnJCw2M2j/5qxBkinZQFobieM8dQ==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.0.tgz",
"integrity": "sha512-W2bIMLYoZ9oow7TyePpMJk9l9LY7O3R61a/68bVCDOtnJynnwe3ZeW2IzzSkrQnPKNdJrxVDn3ALZNisSBwb7g==",
"dev": true
},
"browserify-cipher": {
@@ -1242,9 +1242,9 @@
}
},
"caniuse-db": {
"version": "1.0.30000743",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000743.tgz",
"integrity": "sha1-vI3yolfPkboCQyImYpWvPe2FIwY=",
"version": "1.0.30000747",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000747.tgz",
"integrity": "sha1-j1vWweXmBFpNTmxqOlktGeGotRQ=",
"dev": true
},
"caseless": {
@@ -1343,9 +1343,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
},
"lazy-cache": {
@@ -1926,9 +1926,9 @@
"dev": true
},
"chalk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
"integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz",
"integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==",
"dev": true
},
"debug": {
@@ -1938,9 +1938,9 @@
"dev": true
},
"eslint": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.8.0.tgz",
"integrity": "sha1-Ip7w41Tg5h2DfHqA/fuoJeGZgV4=",
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.9.0.tgz",
"integrity": "sha1-doedJ0BoJhsZH+Dy9Wx0wvQgjos=",
"dev": true
},
"esprima": {
@@ -1968,9 +1968,9 @@
"dev": true
},
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
}
}
@@ -2024,9 +2024,9 @@
"dev": true
},
"chalk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
"integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz",
"integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==",
"dev": true
},
"duplexer2": {
@@ -2112,9 +2112,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
},
"load-json-file": {
@@ -2204,9 +2204,9 @@
"dev": true
},
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
},
"yargs": {
@@ -2330,9 +2330,9 @@
"optional": true
},
"electron-to-chromium": {
"version": "1.3.24",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz",
"integrity": "sha1-m3uIuwXOufoBahd4M8wt3jiPIbY=",
"version": "1.3.26",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.26.tgz",
"integrity": "sha1-mWQnKUhhp02cfIK5Jg6jAejALWY=",
"dev": true
},
"elliptic": {
@@ -2389,15 +2389,15 @@
"dev": true
},
"es5-ext": {
"version": "0.10.30",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
"integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
"version": "0.10.35",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz",
"integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=",
"dev": true
},
"es6-iterator": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
"integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
"dev": true,
"dependencies": {
"d": {
@@ -3941,9 +3941,9 @@
}
},
"handlebars": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz",
"integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=",
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
"integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=",
"dev": true,
"dependencies": {
"source-map": {
@@ -4215,9 +4215,9 @@
"dev": true
},
"chalk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
"integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz",
"integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==",
"dev": true
},
"figures": {
@@ -4245,9 +4245,9 @@
"dev": true
},
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
}
}
@@ -4384,9 +4384,9 @@
"dev": true,
"dependencies": {
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -5040,9 +5040,9 @@
"dev": true
},
"mdast-util-to-hast": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-2.4.3.tgz",
"integrity": "sha1-zXh0yYMmJ/E0/TdWFjhz+T8rHeM=",
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-2.5.0.tgz",
"integrity": "sha1-8IeETSVcdUDzaQbaMLoQbA7l7i8=",
"dev": true
},
"mdast-util-to-string": {
@@ -5251,9 +5251,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -5383,9 +5383,9 @@
"dev": true,
"dependencies": {
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -5910,9 +5910,9 @@
"dev": true
},
"private": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz",
"integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=",
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
"dev": true
},
"process": {
@@ -6065,9 +6065,9 @@
}
},
"rc": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
"integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz",
"integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=",
"dependencies": {
"minimist": {
"version": "1.2.0",
@@ -6536,9 +6536,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -6854,9 +6854,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -7114,9 +7114,9 @@
"dev": true
},
"chalk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
"integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz",
"integrity": "sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==",
"dev": true
},
"is-fullwidth-code-point": {
@@ -7138,9 +7138,9 @@
"dev": true
},
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
}
}
@@ -7312,9 +7312,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
}
}
@@ -7422,9 +7422,9 @@
"dev": true
},
"ua-parser-js": {
"version": "0.7.14",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz",
"integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o=",
"version": "0.7.17",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
"integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==",
"dev": true
},
"uglify-js": {
@@ -7672,9 +7672,9 @@
"dev": true
},
"kind-of": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.0.2.tgz",
"integrity": "sha512-ru8+TQHbN8956c7ZlkgK5Imjx0GMat3jN45GNIthpPeb+SzLrqSg/NG7llQtIqUTbrdu5Oi0lSnIoJmDTwwSzw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
"dev": true
},
"lazy-cache": {
@@ -7769,9 +7769,9 @@
"dev": true,
"dependencies": {
"supports-color": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
"integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.14.2",
"version": "5.13.0-rc.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": {
-1
View File
@@ -48,7 +48,6 @@ function setup()
'toll_booth',
'sally_port',
'gate',
'lift_gate',
'no',
'block'
},
+3 -3
View File
@@ -1,6 +1,6 @@
-- Car profile
api_version = 4
api_version = 3
Set = require('lib/set')
Sequence = require('lib/sequence')
@@ -420,14 +420,14 @@ function process_turn(profile, turn)
turn.duration = profile.properties.traffic_light_penalty
end
if turn.number_of_roads > 2 or turn.source_mode ~= turn.target_mode or turn.is_u_turn then
if turn.turn_type ~= turn_type.no_turn then
if turn.angle >= 0 then
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
else
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
end
if turn.is_u_turn then
if turn.direction_modifier == direction_modifier.u_turn then
turn.duration = turn.duration + profile.properties.u_turn_penalty
end
end
-1
View File
@@ -33,7 +33,6 @@ function setup()
'toll_booth',
'sally_port',
'gate',
'lift_gate',
'no',
'kerb',
'block'
+1 -1
View File
@@ -563,7 +563,7 @@ function WayHandlers.driving_side(profile, way, result, data)
elseif driving_side == 'right' then
result.is_left_hand_driving = false
else
result.is_left_hand_driving = profile.properties.left_hand_driving
result.is_left_hand_driving = profile.left_hand_driving
end
end
+1 -1
View File
@@ -384,7 +384,7 @@ void RenumberData(std::vector<RemainingNodeData> &remaining_nodes,
// we need to make a copy here because we are going to modify it
auto to_orig = new_to_old_node_id;
auto new_node_id = 0u;
auto new_node_id = 0;
// All remaining nodes get the low IDs
for (auto &remaining : remaining_nodes)
+128 -9
View File
@@ -1,7 +1,5 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "engine/api/json_factory.hpp"
#include "engine/hint.hpp"
#include "engine/polyline_compressor.hpp"
#include "util/integer_range.hpp"
@@ -34,6 +32,59 @@ namespace json
namespace detail
{
const constexpr char *modifier_names[] = {"uturn",
"sharp right",
"right",
"slight right",
"straight",
"slight left",
"left",
"sharp left"};
/**
* Human readable values for TurnType enum values
*/
struct TurnTypeName
{
// String value we return with our API
const char *external_name;
// Internal only string name for the turn type - useful for debugging
// and used by debug tiles for visualizing hidden turn types
const char *internal_name;
};
// Indexes in this list correspond to the Enum values of osrm::extractor::guidance::TurnType
const constexpr TurnTypeName turn_type_names[] = {
{"invalid", "(not set)"},
{"new name", "new name"},
{"continue", "continue"},
{"turn", "turn"},
{"merge", "merge"},
{"on ramp", "on ramp"},
{"off ramp", "off ramp"},
{"fork", "fork"},
{"end of road", "end of road"},
{"notification", "notification"},
{"roundabout", "enter roundabout"},
{"exit roundabout", "enter and exit roundabout"},
{"rotary", "enter rotary"},
{"exit rotary", "enter and exit rotary"},
{"roundabout turn", "enter roundabout turn"},
{"roundabout turn", "enter and exit roundabout turn"},
{"use lane", "use lane"},
{"invalid", "(noturn)"},
{"invalid", "(suppressed)"},
{"roundabout", "roundabout"},
{"exit roundabout", "exit roundabout"},
{"rotary", "rotary"},
{"exit rotary", "exit rotary"},
{"roundabout turn", "roundabout turn"},
{"exit roundabout", "exit roundabout turn"},
{"invalid", "(stay on roundabout)"},
{"invalid", "(sliproad)"}};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
// Check whether to include a modifier in the result of the API
inline bool isValidModifier(const guidance::StepManeuver maneuver)
{
@@ -46,6 +97,20 @@ inline bool hasValidLanes(const guidance::IntermediateIntersection &intersection
return intersection.lanes.lanes_in_turn > 0;
}
std::string instructionTypeToString(const TurnType::Enum type)
{
static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType,
"Some turn types have no string representation.");
return turn_type_names[static_cast<std::size_t>(type)].external_name;
}
std::string internalInstructionTypeToString(const TurnType::Enum type)
{
static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType,
"Some turn types have no string representation.");
return turn_type_names[static_cast<std::size_t>(type)].internal_name;
}
util::json::Array lanesFromIntersection(const guidance::IntermediateIntersection &intersection)
{
BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1);
@@ -70,7 +135,13 @@ util::json::Array lanesFromIntersection(const guidance::IntermediateIntersection
return result;
}
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
std::string instructionModifierToString(const DirectionModifier::Enum modifier)
{
static_assert(sizeof(modifier_names) / sizeof(modifier_names[0]) >=
DirectionModifier::MaxDirectionModifier,
"Some direction modifiers has not string representation.");
return modifier_names[static_cast<std::size_t>(modifier)];
}
std::string waypointTypeToString(const guidance::WaypointType waypoint_type)
{
@@ -88,6 +159,55 @@ util::json::Array coordinateToLonLat(const util::Coordinate coordinate)
return array;
}
// FIXME this actually needs to be configurable from the profiles
std::string modeToString(const extractor::TravelMode mode)
{
std::string token;
switch (mode)
{
case TRAVEL_MODE_INACCESSIBLE:
token = "inaccessible";
break;
case TRAVEL_MODE_DRIVING:
token = "driving";
break;
case TRAVEL_MODE_CYCLING:
token = "cycling";
break;
case TRAVEL_MODE_WALKING:
token = "walking";
break;
case TRAVEL_MODE_FERRY:
token = "ferry";
break;
case TRAVEL_MODE_TRAIN:
token = "train";
break;
case TRAVEL_MODE_PUSHING_BIKE:
token = "pushing bike";
break;
case TRAVEL_MODE_STEPS_UP:
token = "steps up";
break;
case TRAVEL_MODE_STEPS_DOWN:
token = "steps down";
break;
case TRAVEL_MODE_RIVER_UP:
token = "river upstream";
break;
case TRAVEL_MODE_RIVER_DOWN:
token = "river downstream";
break;
case TRAVEL_MODE_ROUTE:
token = "route";
break;
default:
token = "other";
break;
}
return token;
}
} // namespace detail
util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
@@ -97,7 +217,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
std::string maneuver_type;
if (maneuver.waypoint_type == guidance::WaypointType::None)
maneuver_type = extractor::guidance::instructionTypeToString(maneuver.instruction.type);
maneuver_type = detail::instructionTypeToString(maneuver.instruction.type);
else
maneuver_type = detail::waypointTypeToString(maneuver.waypoint_type);
@@ -107,8 +227,8 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
step_maneuver.values["type"] = std::move(maneuver_type);
if (detail::isValidModifier(maneuver))
step_maneuver.values["modifier"] = extractor::guidance::instructionModifierToString(
maneuver.instruction.direction_modifier);
step_maneuver.values["modifier"] =
detail::instructionModifierToString(maneuver.instruction.direction_modifier);
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
step_maneuver.values["bearing_before"] = detail::roundAndClampBearing(maneuver.bearing_before);
@@ -192,10 +312,9 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
}
}
route_step.values["mode"] = extractor::travelModeToString(std::move(step.mode));
route_step.values["mode"] = detail::modeToString(std::move(step.mode));
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
route_step.values["geometry"] = std::move(geometry);
route_step.values["driving_side"] = step.is_left_hand_driving ? "left" : "right";
util::json::Array intersections;
intersections.values.reserve(step.intersections.size());
@@ -41,14 +41,15 @@ bool noIntermediaryIntersections(const RouteStep &step)
}
// Link roads, as far as we are concerned, are short unnamed segments between to named segments.
bool isLinkRoad(const RouteStep &pre_link_step,
bool isLinkroad(const RouteStep &pre_link_step,
const RouteStep &link_step,
const RouteStep &post_link_step)
{
const constexpr double MAX_LINK_ROAD_LENGTH = 2 * MAX_COLLAPSE_DISTANCE;
const auto is_short = link_step.distance <= MAX_LINK_ROAD_LENGTH;
const auto unnamed = link_step.name.empty();
const auto between_named = !pre_link_step.name.empty() && !post_link_step.name.empty();
const auto unnamed = link_step.name_id == EMPTY_NAMEID;
const auto between_named =
(pre_link_step.name_id != EMPTY_NAMEID) && (post_link_step.name_id != EMPTY_NAMEID);
return is_short && unnamed && between_named && noIntermediaryIntersections(link_step);
}
@@ -195,7 +196,7 @@ bool isUTurn(const RouteStepIterator step_prior_to_intersection,
const auto only_allowed_turn = (numberOfAllowedTurns(*step_leaving_intersection) == 1) &&
noIntermediaryIntersections(*step_entering_intersection);
return collapsable || isLinkRoad(*step_prior_to_intersection,
return collapsable || isLinkroad(*step_prior_to_intersection,
*step_entering_intersection,
*step_leaving_intersection) ||
only_allowed_turn;
+10 -13
View File
@@ -51,15 +51,15 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
util::bearing::angleBetween(entry_step_entry_bearing, exit_step_exit_bearing);
// both angles are in the same direction, the total turn gets increased
//
// 
// a ---- b
// \
// \ 
// c
// |
// d
//
// Will be considered just like
//
// 
// a -----b
// |
// c
@@ -89,11 +89,11 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
else
{
// to prevent ignoring angles like
//
// 
// a -- b
// |
// c -- d
//
// 
// We don't combine both turn angles here but keep the very first turn angle.
// We choose the first one, since we consider the first maneuver in a merge range the
// important one
@@ -186,9 +186,8 @@ void AdjustToCombinedTurnStrategy::operator()(RouteStep &step_at_turn_location,
{
const auto angle = findTotalTurnAngle(step_at_turn_location, transfer_from_step);
// Forks and merges point to left/right. By doing a combined angle, we would risk ending up with
// unreasonable fork instrucitons. The direction of a fork or a merge only depends on the
// location,
// Forks point to left/right. By doing a combined angle, we would risk ending up with
// unreasonable fork instrucitons. The direction of a fork only depends on the forking location,
// not further angles coming up
//
// d
@@ -196,8 +195,7 @@ void AdjustToCombinedTurnStrategy::operator()(RouteStep &step_at_turn_location,
// a - b
//
// could end up as `fork left` for `a-b-c`, instead of fork-right
const auto new_modifier = hasTurnType(step_at_turn_location, TurnType::Fork) ||
hasTurnType(step_at_turn_location, TurnType::Merge)
const auto new_modifier = hasTurnType(step_at_turn_location, TurnType::Fork)
? step_at_turn_location.maneuver.instruction.direction_modifier
: getTurnDirection(angle);
@@ -441,14 +439,13 @@ RouteSteps collapseTurnInstructions(RouteSteps steps)
TransferSignageStrategy(),
NoModificationStrategy());
}
// if the current collapsing triggers, we can check for advanced scenarios that only are
// possible after an inital collapse step (e.g. name change right after a u-turn)
//
// 
// f - e - d
// | |
// a - b - c
//
// 
// In this scenario, bc and de might belong to a different road than a-b and f-e (since
// there are no fix conventions how to label them in segregated intersections). These steps
// might only become apparent after some initial collapsing
+29 -151
View File
@@ -1,7 +1,5 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/plugins/plugin_base.hpp"
#include "engine/plugins/tile.hpp"
#include "engine/plugins/plugin_base.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/string_view.hpp"
@@ -69,7 +67,7 @@ template <typename T> struct ValueIndexer
return offset;
}
std::size_t indexOf(const T &value) { return value_offsets[value]; }
std::size_t indexOf(const T &value) { return value_offsets[value]; };
const std::vector<T> &values() { return used_values; }
@@ -184,8 +182,25 @@ inline void encodePoint(const FixedPoint &pt, protozero::packed_field_uint32 &ge
geometry.add_element(protozero::encode_zigzag32(dy));
}
linestring_t floatLineToTileLine(const FloatLine &geo_line, const BBox &tile_bbox)
/**
* Returnx the x1,y1,x2,y2 pixel coordinates of a line in a given
* tile.
*
* @param start the first coordinate of the line
* @param target the last coordinate of the line
* @param tile_bbox the boundaries of the tile, in mercator coordinates
* @return a FixedLine with coordinates relative to the tile_bbox.
*/
FixedLine coordinatesToTileLine(const util::Coordinate start,
const util::Coordinate target,
const BBox &tile_bbox)
{
FloatLine geo_line;
geo_line.emplace_back(static_cast<double>(util::toFloating(start.lon)),
static_cast<double>(util::toFloating(start.lat)));
geo_line.emplace_back(static_cast<double>(util::toFloating(target.lon)),
static_cast<double>(util::toFloating(target.lat)));
linestring_t unclipped_line;
for (auto const &pt : geo_line)
@@ -204,65 +219,8 @@ linestring_t floatLineToTileLine(const FloatLine &geo_line, const BBox &tile_bbo
boost::geometry::append(unclipped_line, point_t(px, py));
}
return unclipped_line;
}
std::vector<FixedLine> coordinatesToTileLine(const std::vector<util::Coordinate> &points,
const BBox &tile_bbox)
{
FloatLine geo_line;
for (auto const &c : points)
{
geo_line.emplace_back(static_cast<double>(util::toFloating(c.lon)),
static_cast<double>(util::toFloating(c.lat)));
}
linestring_t unclipped_line = floatLineToTileLine(geo_line, tile_bbox);
multi_linestring_t clipped_line;
boost::geometry::intersection(clip_box, unclipped_line, clipped_line);
std::vector<FixedLine> result;
// b::g::intersection might return a line with one point if the
// original line was very short and coords were dupes
for (auto const &cl : clipped_line)
{
if (cl.size() < 2)
continue;
FixedLine tile_line;
for (const auto &p : cl)
tile_line.emplace_back(p.get<0>(), p.get<1>());
result.emplace_back(std::move(tile_line));
}
return result;
}
/**
* Return the x1,y1,x2,y2 pixel coordinates of a line in a given
* tile.
*
* @param start the first coordinate of the line
* @param target the last coordinate of the line
* @param tile_bbox the boundaries of the tile, in mercator coordinates
* @return a FixedLine with coordinates relative to the tile_bbox.
*/
FixedLine coordinatesToTileLine(const util::Coordinate start,
const util::Coordinate target,
const BBox &tile_bbox)
{
FloatLine geo_line;
geo_line.emplace_back(static_cast<double>(util::toFloating(start.lon)),
static_cast<double>(util::toFloating(start.lat)));
geo_line.emplace_back(static_cast<double>(util::toFloating(target.lon)),
static_cast<double>(util::toFloating(target.lat)));
linestring_t unclipped_line = floatLineToTileLine(geo_line, tile_bbox);
multi_linestring_t clipped_line;
boost::geometry::intersection(clip_box, unclipped_line, clipped_line);
FixedLine tile_line;
@@ -271,9 +229,12 @@ FixedLine coordinatesToTileLine(const util::Coordinate start,
// original line was very short and coords were dupes
if (!clipped_line.empty() && clipped_line[0].size() == 2)
{
for (const auto &p : clipped_line[0])
if (clipped_line[0].size() == 2)
{
tile_line.emplace_back(p.get<0>(), p.get<1>());
for (const auto &p : clipped_line[0])
{
tile_line.emplace_back(p.get<0>(), p.get<1>());
}
}
}
@@ -347,20 +308,6 @@ std::vector<std::size_t> getEdgeIndex(const std::vector<RTreeLeaf> &edges)
return sorted_edge_indexes;
}
std::vector<NodeID> getSegregatedNodes(const DataFacadeBase &facade,
const std::vector<RTreeLeaf> &edges)
{
std::vector<NodeID> result;
for (RTreeLeaf const &e : edges)
{
if (e.forward_segment_id.enabled && facade.IsSegregated(e.forward_segment_id.id))
result.push_back(e.forward_segment_id.id);
}
return result;
}
void encodeVectorTile(const DataFacadeBase &facade,
unsigned x,
unsigned y,
@@ -368,7 +315,6 @@ void encodeVectorTile(const DataFacadeBase &facade,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes,
const std::vector<routing_algorithms::TurnData> &all_turn_data,
const std::vector<NodeID> &segregated_nodes,
std::string &pbf_buffer)
{
@@ -766,10 +712,10 @@ void encodeVectorTile(const DataFacadeBase &facade,
point_float_index.add(t.weight / 10.0); // Note conversion to float here
auto turntype_idx =
point_string_index.add(extractor::guidance::internalInstructionTypeToString(
point_string_index.add(api::json::detail::internalInstructionTypeToString(
t.turn_instruction.type));
auto turnmodifier_idx =
point_string_index.add(extractor::guidance::instructionModifierToString(
point_string_index.add(api::json::detail::instructionModifierToString(
t.turn_instruction.direction_modifier));
return EncodedTurnData{t.coordinate,
angle_idx,
@@ -919,66 +865,6 @@ void encodeVectorTile(const DataFacadeBase &facade,
}
}
}
{
protozero::pbf_writer line_layer_writer(tile_writer, util::vector_tile::LAYER_TAG);
line_layer_writer.add_uint32(util::vector_tile::VERSION_TAG, 2); // version
line_layer_writer.add_string(util::vector_tile::NAME_TAG, "internal-nodes"); // name
line_layer_writer.add_uint32(util::vector_tile::EXTENT_TAG,
util::vector_tile::EXTENT); // extent
unsigned id = 0;
for (auto edgeNodeID : segregated_nodes)
{
auto const geomIndex = facade.GetGeometryIndex(edgeNodeID);
std::vector<NodeID> geometry;
if (geomIndex.forward)
geometry = facade.GetUncompressedForwardGeometry(geomIndex.id);
else
geometry = facade.GetUncompressedReverseGeometry(geomIndex.id);
std::vector<util::Coordinate> points;
for (auto const nodeID : geometry)
points.push_back(facade.GetCoordinateOfNode(nodeID));
const auto encode_tile_line = [&line_layer_writer, &id](
const FixedLine &tile_line, std::int32_t &start_x, std::int32_t &start_y) {
protozero::pbf_writer feature_writer(line_layer_writer,
util::vector_tile::FEATURE_TAG);
feature_writer.add_enum(util::vector_tile::GEOMETRY_TAG,
util::vector_tile::GEOMETRY_TYPE_LINE); // geometry type
feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
{
protozero::packed_field_uint32 field(
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
}
{
// Encode the geometry for the feature
protozero::packed_field_uint32 geometry(
feature_writer, util::vector_tile::FEATURE_GEOMETRIES_TAG);
encodeLinestring(tile_line, geometry, start_x, start_y);
}
};
std::int32_t start_x = 0;
std::int32_t start_y = 0;
auto tile_lines = coordinatesToTileLine(points, tile_bbox);
if (!tile_lines.empty())
{
for (auto const &tl : tile_lines)
{
encode_tile_line(tl, start_x, start_y);
}
}
}
}
}
// protozero serializes data during object destructors, so once the scope closes,
// our result buffer will have all the tile data encoded into it.
@@ -993,7 +879,6 @@ Status TilePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
const auto &facade = algorithms.GetFacade();
auto edges = getEdges(facade, parameters.x, parameters.y, parameters.z);
auto segregated_nodes = getSegregatedNodes(facade, edges);
auto edge_index = getEdgeIndex(edges);
@@ -1006,15 +891,8 @@ Status TilePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
turns = algorithms.GetTileTurns(edges, edge_index);
}
encodeVectorTile(facade,
parameters.x,
parameters.y,
parameters.z,
edges,
edge_index,
turns,
segregated_nodes,
pbf_buffer);
encodeVectorTile(
facade, parameters.x, parameters.y, parameters.z, edges, edge_index, turns, pbf_buffer);
return Status::Ok;
}
@@ -233,12 +233,6 @@ RandIt filterPackedPathsByCellSharing(RandIt first, RandIt last, const Partition
cells.insert(get_cell(std::get<1>(edge)));
const auto over_sharing_limit = [&](const auto &packed) {
if (packed.path.empty())
{ // don't remove routes with single-node (empty) path
return false;
}
const auto not_seen = [&](const PackedEdge edge) {
const auto source_cell = get_cell(std::get<0>(edge));
const auto target_cell = get_cell(std::get<1>(edge));
@@ -316,7 +310,7 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
// Check plateaux edges towards the target. Terminates at the source / target
// at the latest, since parent(target)==target for the reverse heap and
// parent(target) != target in the forward heap (and vice versa).
while (node != fst.GetData(node).parent && has_plateaux_at_node(node, fst, snd))
while (has_plateaux_at_node(node, fst, snd))
node = fst.GetData(node).parent;
return node;
@@ -326,11 +320,7 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
BOOST_ASSERT(packed.via.node != path.via.node);
BOOST_ASSERT(packed.via.weight != INVALID_EDGE_WEIGHT);
BOOST_ASSERT(packed.via.node != SPECIAL_NODEID);
if (packed.path.empty())
{ // the edge case when packed.via.node is both source and target node
return false;
}
BOOST_ASSERT(!packed.path.empty());
const NodeID via = packed.via.node;
@@ -405,12 +395,6 @@ template <typename RandIt> RandIt filterUnpackedPathsBySharing(RandIt first, Ran
edges.insert(begin(shortest_path.edges), begin(shortest_path.edges));
const auto over_sharing_limit = [&](const auto &unpacked) {
if (unpacked.edges.empty())
{ // don't remove routes with single-node (empty) path
return false;
}
const auto not_seen = [&](const EdgeID edge) { return edges.count(edge) < 1; };
const auto different = std::count_if(begin(unpacked.edges), end(unpacked.edges), not_seen);
@@ -784,8 +768,9 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
begin(weighted_packed_paths) + 1,
alternative_paths_last);
alternative_paths_last = filterPackedPathsByCellSharing(
begin(weighted_packed_paths), alternative_paths_last, partition);
alternative_paths_last = filterPackedPathsByCellSharing(begin(weighted_packed_paths), //
end(weighted_packed_paths), //
partition); //
BOOST_ASSERT(weighted_packed_paths.size() >= 1);
+3 -16
View File
@@ -67,13 +67,12 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::unordered_set<NodeID> &traffic_lights,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const std::unordered_set<EdgeID> &segregated_edges,
guidance::LaneDescriptionMap &lane_description_map)
: m_edge_based_node_container(node_data_container), m_number_of_edge_based_nodes(0),
m_coordinates(coordinates), m_node_based_graph(std::move(node_based_graph)),
m_barrier_nodes(barrier_nodes), m_traffic_lights(traffic_lights),
m_compressed_edge_container(compressed_edge_container), name_table(name_table),
segregated_edges(segregated_edges), lane_description_map(lane_description_map)
lane_description_map(lane_description_map)
{
}
@@ -165,19 +164,13 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
forward_data.geometry_id;
m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_1]].annotation_id =
forward_data.annotation_data;
m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_1]].segregated =
segregated_edges.count(edge_id_1) > 0;
if (nbe_to_ebn_mapping[edge_id_2] != SPECIAL_EDGEID)
{
m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_2]].geometry_id =
reverse_data.geometry_id;
m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_2]].annotation_id =
reverse_data.annotation_data;
m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_2]].segregated =
segregated_edges.count(edge_id_2) > 0;
}
// Add segments of edge-based nodes
for (const auto i : util::irange(std::size_t{0}, segment_count))
{
@@ -372,8 +365,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
edge_data.geometry_id;
m_edge_based_node_container.nodes[edge_based_node_id].annotation_id =
edge_data.annotation_data;
m_edge_based_node_container.nodes[edge_based_node_id].segregated =
segregated_edges.count(eid) > 0;
m_edge_based_node_weights.push_back(m_edge_based_node_weights[eid]);
@@ -578,16 +569,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// compute weight and duration penalties
auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection);
ExtractionTurn extracted_turn(
turn.angle,
m_node_based_graph.GetOutDegree(node_at_center_of_intersection),
turn.instruction.direction_modifier == guidance::DirectionModifier::UTurn,
turn,
is_traffic_light,
edge_data1.flags.restricted,
edge_data2.flags.restricted,
m_edge_based_node_container.GetAnnotation(edge_data1.annotation_data)
.is_left_hand_driving,
m_edge_based_node_container.GetAnnotation(edge_data1.annotation_data).travel_mode,
m_edge_based_node_container.GetAnnotation(edge_data2.annotation_data).travel_mode);
.is_left_hand_driving);
scripting_environment.ProcessTurn(extracted_turn);
// turn penalties are limited to [-2^15, 2^15) which roughly
-239
View File
@@ -217,15 +217,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
turn_restrictions,
conditional_turn_restrictions);
util::Log() << "Find segregated edges in node-based graph ..." << std::flush;
TIMER_START(segregated);
auto segregated_edges = FindSegregatedNodes(node_based_graph_factory);
TIMER_STOP(segregated);
util::Log() << "ok, after " << TIMER_SEC(segregated) << "s";
util::Log() << "Segregated edges count = " << segregated_edges.size();
util::Log() << "Writing nodes for nodes-based and edges-based graphs ...";
auto const &coordinates = node_based_graph_factory.GetCoordinates();
files::writeNodes(
@@ -277,7 +268,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
traffic_signals,
turn_restrictions,
conditional_turn_restrictions,
segregated_edges,
turn_lane_map,
scripting_environment,
edge_based_nodes_container,
@@ -665,7 +655,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
const std::unordered_set<NodeID> &traffic_signals,
const std::vector<TurnRestriction> &turn_restrictions,
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
const std::unordered_set<EdgeID> &segregated_edges,
// might have to be updated to add new lane combinations
guidance::LaneDescriptionMap &turn_lane_map,
// for calculating turn penalties
@@ -687,7 +676,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
traffic_signals,
coordinates,
name_table,
segregated_edges,
turn_lane_map);
const auto create_edge_based_edges = [&]() {
@@ -838,232 +826,5 @@ void Extractor::WriteCompressedNodeBasedGraph(const std::string &path,
}
}
struct EdgeInfo
{
NodeID node;
util::StringView name;
// 0 - outgoing (forward), 1 - incoming (reverse), 2 - both outgoing and incoming
int direction;
ClassData road_class;
guidance::RoadPriorityClass::Enum road_priority_class;
struct LessName
{
bool operator()(EdgeInfo const &e1, EdgeInfo const &e2) const { return e1.name < e2.name; }
};
};
bool IsSegregated(std::vector<EdgeInfo> v1,
std::vector<EdgeInfo> v2,
EdgeInfo const &current,
double edgeLength)
{
if (v1.size() < 2 || v2.size() < 2)
return false;
auto const sort_by_name_fn = [](std::vector<EdgeInfo> &v) {
std::sort(v.begin(), v.end(), EdgeInfo::LessName());
};
sort_by_name_fn(v1);
sort_by_name_fn(v2);
// Internal edge with the name should be connected with any other neibour edge with the same
// name, e.g. isolated edge with unique name is not segregated.
// b - 'b' road continues here
// |
// - - a - |
// b - segregated edge
// - - a - |
if (!current.name.empty())
{
auto const findNameFn = [&current](std::vector<EdgeInfo> const &v) {
return std::binary_search(v.begin(), v.end(), current, EdgeInfo::LessName());
};
if (!findNameFn(v1) && !findNameFn(v2))
return false;
}
// set_intersection like routine to get equal result pairs
std::vector<std::pair<EdgeInfo const *, EdgeInfo const *>> commons;
auto i1 = v1.begin();
auto i2 = v2.begin();
while (i1 != v1.end() && i2 != v2.end())
{
if (i1->name == i2->name)
{
if (!i1->name.empty())
commons.push_back(std::make_pair(&(*i1), &(*i2)));
++i1;
++i2;
}
else if (i1->name < i2->name)
++i1;
else
++i2;
}
if (commons.size() < 2)
return false;
auto const check_equal_class = [](std::pair<EdgeInfo const *, EdgeInfo const *> const &e) {
// Or (e.first->road_class & e.second->road_class != 0)
return e.first->road_class == e.second->road_class;
};
size_t equal_class_count = 0;
for (auto const &e : commons)
if (check_equal_class(e))
++equal_class_count;
if (equal_class_count < 2)
return false;
auto const get_length_threshold = [](EdgeInfo const *e) {
switch (e->road_priority_class)
{
case guidance::RoadPriorityClass::MOTORWAY:
case guidance::RoadPriorityClass::TRUNK:
return 30.0;
case guidance::RoadPriorityClass::PRIMARY:
return 20.0;
case guidance::RoadPriorityClass::SECONDARY:
case guidance::RoadPriorityClass::TERTIARY:
return 10.0;
default:
return 5.0;
}
};
double threshold = std::numeric_limits<double>::max();
for (auto const &e : commons)
threshold =
std::min(threshold, get_length_threshold(e.first) + get_length_threshold(e.second));
return edgeLength <= threshold;
}
std::unordered_set<EdgeID> Extractor::FindSegregatedNodes(NodeBasedGraphFactory &factory)
{
util::NameTable names(config.GetPath(".osrm.names").string());
auto const &graph = factory.GetGraph();
auto const &annotation = factory.GetAnnotationData();
guidance::CoordinateExtractor coordExtractor(
graph, factory.GetCompressedEdges(), factory.GetCoordinates());
auto const get_edge_length = [&](NodeID from_node, EdgeID edgeID, NodeID to_node) {
auto const geom = coordExtractor.GetCoordinatesAlongRoad(from_node, edgeID, false, to_node);
double length = 0.0;
for (size_t i = 1; i < geom.size(); ++i)
{
length += osrm::util::coordinate_calculation::haversineDistance(geom[i - 1], geom[i]);
}
return length;
};
auto const get_edge_info = [&](NodeID node, auto const &edgeData) -> EdgeInfo {
/// @todo Make string normalization/lowercase/trim for comparison ...
auto const id = annotation[edgeData.annotation_data].name_id;
BOOST_ASSERT(id != INVALID_NAMEID);
auto const name = names.GetNameForID(id);
return {node,
name,
edgeData.reversed ? 1 : 0,
annotation[edgeData.annotation_data].classes,
edgeData.flags.road_classification.GetClass()};
};
auto const collect_edge_info_fn = [&](auto const &edges1, NodeID node2) {
std::vector<EdgeInfo> info;
for (auto const &e : edges1)
{
NodeID const target = graph.GetTarget(e);
if (target == node2)
continue;
info.push_back(get_edge_info(target, graph.GetEdgeData(e)));
}
if (info.empty())
return info;
std::sort(info.begin(), info.end(), [](EdgeInfo const &e1, EdgeInfo const &e2) {
return e1.node < e2.node;
});
// Merge equal infos with correct direction.
auto curr = info.begin();
auto next = curr;
while (++next != info.end())
{
if (curr->node == next->node)
{
BOOST_ASSERT(curr->name == next->name);
BOOST_ASSERT(curr->road_class == next->road_class);
BOOST_ASSERT(curr->direction != next->direction);
curr->direction = 2;
}
else
curr = next;
}
info.erase(
std::unique(info.begin(),
info.end(),
[](EdgeInfo const &e1, EdgeInfo const &e2) { return e1.node == e2.node; }),
info.end());
return info;
};
auto const isSegregatedFn = [&](auto const &edgeData,
auto const &edges1,
NodeID node1,
auto const &edges2,
NodeID node2,
double edgeLength) {
return IsSegregated(collect_edge_info_fn(edges1, node2),
collect_edge_info_fn(edges2, node1),
get_edge_info(node1, edgeData),
edgeLength);
};
std::unordered_set<EdgeID> segregated_edges;
for (NodeID sourceID = 0; sourceID < graph.GetNumberOfNodes(); ++sourceID)
{
auto const sourceEdges = graph.GetAdjacentEdgeRange(sourceID);
for (EdgeID edgeID : sourceEdges)
{
auto const &edgeData = graph.GetEdgeData(edgeID);
if (edgeData.reversed)
continue;
NodeID const targetID = graph.GetTarget(edgeID);
auto const targetEdges = graph.GetAdjacentEdgeRange(targetID);
double const length = get_edge_length(sourceID, edgeID, targetID);
if (isSegregatedFn(edgeData, sourceEdges, sourceID, targetEdges, targetID, length))
segregated_edges.insert(edgeID);
}
}
return segregated_edges;
}
} // namespace extractor
} // namespace osrm
+9 -10
View File
@@ -90,19 +90,18 @@ void ExtractorCallbacks::ProcessRestriction(const InputConditionalTurnRestrictio
*/
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
{
if ((parsed_way.forward_travel_mode == extractor::TRAVEL_MODE_INACCESSIBLE ||
if ((parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
parsed_way.forward_speed <= 0) &&
(parsed_way.backward_travel_mode == extractor::TRAVEL_MODE_INACCESSIBLE ||
(parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
parsed_way.backward_speed <= 0) &&
parsed_way.duration <= 0)
{ // Only true if the way is assigned a valid speed/duration
return;
}
if (!fallback_to_duration &&
(parsed_way.forward_travel_mode == extractor::TRAVEL_MODE_INACCESSIBLE ||
parsed_way.forward_rate <= 0) &&
(parsed_way.backward_travel_mode == extractor::TRAVEL_MODE_INACCESSIBLE ||
if (!fallback_to_duration && (parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
parsed_way.forward_rate <= 0) &&
(parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE ||
parsed_way.backward_rate <= 0) &&
parsed_way.weight <= 0)
{ // Only true if the way is assigned a valid rate/weight and there is no duration fallback
@@ -146,7 +145,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
}
};
if (parsed_way.forward_travel_mode != extractor::TRAVEL_MODE_INACCESSIBLE)
if (parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
{
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.forward_speed > 0);
forward_duration_data =
@@ -163,7 +162,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.forward_rate);
}
}
if (parsed_way.backward_travel_mode != extractor::TRAVEL_MODE_INACCESSIBLE)
if (parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
{
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.backward_speed > 0);
backward_duration_data =
@@ -381,12 +380,12 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
const bool in_forward_direction =
(parsed_way.forward_speed > 0 || parsed_way.forward_rate > 0 || parsed_way.duration > 0 ||
parsed_way.weight > 0) &&
(parsed_way.forward_travel_mode != extractor::TRAVEL_MODE_INACCESSIBLE);
(parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
const bool in_backward_direction =
(parsed_way.backward_speed > 0 || parsed_way.backward_rate > 0 || parsed_way.duration > 0 ||
parsed_way.weight > 0) &&
(parsed_way.backward_travel_mode != extractor::TRAVEL_MODE_INACCESSIBLE);
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
// split an edge into two edges if forwards/backwards behavior differ
const bool split_edge =
+1 -6
View File
@@ -221,15 +221,10 @@ void GraphCompressor::Compress(
// generate an artifical turn for the turn penalty generation
ExtractionTurn extraction_turn(
0,
2,
false,
true,
fwd_edge_data1.flags.restricted,
fwd_edge_data2.flags.restricted,
node_data_container[fwd_edge_data1.annotation_data].is_left_hand_driving,
TRAVEL_MODE_DRIVING,
TRAVEL_MODE_DRIVING);
node_data_container[fwd_edge_data1.annotation_data].is_left_hand_driving);
scripting_environment.ProcessTurn(extraction_turn);
node_duration_penalty = extraction_turn.duration * 10;
@@ -71,19 +71,17 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge,
if (!on_ramp && onto_ramp)
return TurnType::OnRamp;
const auto &in_name_id =
const auto &in_name =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
.name_id;
const auto &out_name_id =
const auto &out_name =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id;
const auto &in_name_empty = name_table.GetNameForID(in_name_id).empty();
const auto &out_name_empty = name_table.GetNameForID(out_name_id).empty();
const auto same_name = !util::guidance::requiresNameAnnounced(
in_name_id, out_name_id, name_table, street_name_suffix_table);
in_name, out_name, name_table, street_name_suffix_table);
if (!in_name_empty && !out_name_empty && same_name)
if (in_name != EMPTY_NAMEID && out_name != EMPTY_NAMEID && same_name)
{
return TurnType::Continue;
}
@@ -490,8 +488,8 @@ bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID t
const auto &target_edge_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(target_edge_id).annotation_data);
return !name_table.GetNameForID(source_edge_data.name_id).empty() && //
!name_table.GetNameForID(target_edge_data.name_id).empty() && //
return source_edge_data.name_id != EMPTY_NAMEID && //
target_edge_data.name_id != EMPTY_NAMEID && //
!util::guidance::requiresNameAnnounced(source_edge_data.name_id,
target_edge_data.name_id,
name_table,
@@ -370,17 +370,6 @@ IntersectionNormalizer::AdjustBearingsForMergeAtDestination(const NodeID node_at
: offset;
};
// only if straighmost angles get smaller, we consider it an improvement
auto const improves_straightmost = [&](auto const index, auto const offset) {
const auto itr = next_intersection_along_road.FindClosestBearing(
util::bearing::reverse(next_intersection_along_road[index].bearing));
const auto angle = util::bearing::angleBetween(
util::bearing::reverse(itr->bearing), next_intersection_along_road[index].bearing);
return util::angularDeviation(angle, STRAIGHT_ANGLE) >
util::angularDeviation(angle + offset, STRAIGHT_ANGLE);
};
// check if the u-turn edge at the next intersection could be merged to the left/right. If
// this is the case and the road is not far away (see previous distance check), if
// influences the perceived angle.
@@ -389,17 +378,13 @@ IntersectionNormalizer::AdjustBearingsForMergeAtDestination(const NodeID node_at
const auto offset =
get_offset(next_intersection_along_road[0], next_intersection_along_road[1]);
if (improves_straightmost(0, -offset) && improves_straightmost(1, offset))
{
const auto corrected_offset = get_corrected_offset(
offset,
road,
intersection[(intersection.size() + index - 1) % intersection.size()]);
// at the target intersection, we merge to the right, so we need to shift the
// current
// angle to the left
road.bearing = adjustAngle(road.bearing, corrected_offset);
}
const auto corrected_offset = get_corrected_offset(
offset,
road,
intersection[(intersection.size() + index - 1) % intersection.size()]);
// at the target intersection, we merge to the right, so we need to shift the current
// angle to the left
road.bearing = adjustAngle(road.bearing, corrected_offset);
}
else if (CanMerge(node_at_next_intersection,
next_intersection_along_road,
@@ -410,18 +395,13 @@ IntersectionNormalizer::AdjustBearingsForMergeAtDestination(const NodeID node_at
get_offset(next_intersection_along_road[0],
next_intersection_along_road[next_intersection_along_road.size() - 1]);
if (improves_straightmost(0, offset) &&
improves_straightmost(next_intersection_along_road.size() - 1, -offset))
{
const auto corrected_offset = get_corrected_offset(
offset, road, intersection[(index + 1) % intersection.size()]);
// at the target intersection, we merge to the left, so we need to shift the current
// angle to the right
road.bearing = adjustAngle(road.bearing, -corrected_offset);
}
const auto corrected_offset =
get_corrected_offset(offset, road, intersection[(index + 1) % intersection.size()]);
// at the target intersection, we merge to the left, so we need to shift the current
// angle to the right
road.bearing = adjustAngle(road.bearing, -corrected_offset);
}
}
return intersection;
}
@@ -23,8 +23,6 @@ namespace guidance
namespace
{
// check a connected road for equality of a name
// returns 'true' if no equality because this is used as a filter elsewhere, i.e. filter if fn
// returns 'true'
inline auto makeCheckRoadForName(const NameID name_id,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
@@ -34,18 +32,15 @@ inline auto makeCheckRoadForName(const NameID name_id,
return [name_id, &node_based_graph, &node_data_container, &name_table, &suffix_table](
const MergableRoadDetector::MergableRoadData &road) {
// since we filter here, we don't want any other name than the one we are looking for
const auto road_name_id =
const auto road_name =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id;
const auto road_name_empty = name_table.GetNameForID(road_name_id).empty();
const auto in_name_empty = name_table.GetNameForID(name_id).empty();
if (in_name_empty || road_name_empty)
if (name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
return true;
const auto requires_announcement =
util::guidance::requiresNameAnnounced(
name_id, road_name_id, name_table, suffix_table) ||
util::guidance::requiresNameAnnounced(road_name_id, name_id, name_table, suffix_table);
util::guidance::requiresNameAnnounced(name_id, road_name, name_table, suffix_table) ||
util::guidance::requiresNameAnnounced(road_name, name_id, name_table, suffix_table);
return requires_announcement;
};
@@ -114,8 +109,7 @@ bool MergableRoadDetector::CanMergeRoad(const NodeID intersection_node,
return true;
// finally check if two roads describe the direction
return HaveSameDirection(intersection_node, lhs, rhs) &&
!IsCircularShape(intersection_node, lhs, rhs);
return HaveSameDirection(intersection_node, lhs, rhs);
}
bool MergableRoadDetector::HaveIdenticalNames(const NameID lhs, const NameID rhs) const
@@ -190,8 +184,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data)
.name_id,
lhs.bearing,
/*requires entry=*/false,
false);
/*requires entry=*/false);
NodeBasedGraphWalker graph_walker(
node_based_graph, node_data_container, intersection_generator);
@@ -277,10 +270,14 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_based_graph.GetTarget(right_accumulator.via_edge_id);
}
bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const
bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const
{
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
return false;
// Find a coordinate following a road that is far away
NodeBasedGraphWalker graph_walker(
node_based_graph, node_data_container, intersection_generator);
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length) {
@@ -289,8 +286,7 @@ bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id,
lhs.bearing,
/*requires_entry=*/false,
false);
/*requires_entry=*/false);
graph_walker.TraverseRoad(intersection_node, edge_id, accumulator, selector);
return std::make_pair(accumulator.accumulated_length, accumulator.coordinates);
@@ -299,12 +295,26 @@ bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
std::vector<util::Coordinate> coordinates_to_the_left, coordinates_to_the_right;
double distance_traversed_to_the_left, distance_traversed_to_the_right;
// many roads only do short parallel segments. To get a good impression of how `parallel` two
// roads are, we look 100 meters down the road (wich can be quite short for very broad roads).
const double constexpr distance_to_extract = 150;
std::tie(distance_traversed_to_the_left, coordinates_to_the_left) =
getCoordinatesAlongWay(lhs.eid, distance_to_extract);
// tuned parameter, if we didn't get as far as 40 meters, we might barely look past an
// intersection.
const auto constexpr MINIMUM_LENGTH_FOR_PARALLEL_DETECTION = 40;
// quit early if the road is not very long
if (distance_traversed_to_the_left <= MINIMUM_LENGTH_FOR_PARALLEL_DETECTION)
return false;
std::tie(distance_traversed_to_the_right, coordinates_to_the_right) =
getCoordinatesAlongWay(rhs.eid, distance_to_extract);
if (distance_traversed_to_the_right <= MINIMUM_LENGTH_FOR_PARALLEL_DETECTION)
return false;
const auto connect_again = (coordinates_to_the_left.back() == coordinates_to_the_right.back());
// Tuning parameter to detect and don't merge roads close to circular shapes
@@ -334,55 +344,9 @@ bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
// then don't merge roads if A/L² is greater than the lower bound
BOOST_ASSERT(area_to_squared_perimeter_ratio <= 1. / (4 * M_PI));
if (area_to_squared_perimeter_ratio >= CIRCULAR_POLYGON_ISOPERIMETRIC_LOWER_BOUND)
return true;
return false;
}
return false;
}
bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const
{
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
return false;
// Find a coordinate following a road that is far away
NodeBasedGraphWalker graph_walker(
node_based_graph, node_data_container, intersection_generator);
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length) {
LengthLimitedCoordinateAccumulator accumulator(coordinate_extractor, max_length);
SelectStraightmostRoadByNameAndOnlyChoice selector(
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id,
lhs.bearing,
/*requires_entry=*/false,
true);
graph_walker.TraverseRoad(intersection_node, edge_id, accumulator, selector);
return std::make_pair(accumulator.accumulated_length, accumulator.coordinates);
};
std::vector<util::Coordinate> coordinates_to_the_left, coordinates_to_the_right;
double distance_traversed_to_the_left, distance_traversed_to_the_right;
std::tie(distance_traversed_to_the_left, coordinates_to_the_left) =
getCoordinatesAlongWay(lhs.eid, distance_to_extract);
// tuned parameter, if we didn't get as far as 40 meters, we might barely look past an
// intersection.
const auto constexpr MINIMUM_LENGTH_FOR_PARALLEL_DETECTION = 40;
// quit early if the road is not very long
if (distance_traversed_to_the_left <= MINIMUM_LENGTH_FOR_PARALLEL_DETECTION)
return false;
std::tie(distance_traversed_to_the_right, coordinates_to_the_right) =
getCoordinatesAlongWay(rhs.eid, distance_to_extract);
if (distance_traversed_to_the_right <= MINIMUM_LENGTH_FOR_PARALLEL_DETECTION)
return false;
const auto connect_again = (coordinates_to_the_left.back() == coordinates_to_the_right.back());
// sampling to correctly weight longer segments in regression calculations
const auto constexpr SAMPLE_INTERVAL = 5;
coordinates_to_the_left = coordinate_extractor.SampleCoordinates(
@@ -431,7 +395,6 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
const auto combined_road_width = 0.5 * (lane_count_lhs + lane_count_rhs) * ASSUMED_LANE_WIDTH;
const auto constexpr MAXIMAL_ALLOWED_SEPARATION_WIDTH = 8;
return distance_between_roads <= combined_road_width + MAXIMAL_ALLOWED_SEPARATION_WIDTH;
}
@@ -470,18 +433,16 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node,
.name_id;
const auto has_required_name = [this, required_name_id](const auto edge_id) {
const auto road_name_id =
const auto road_name =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id;
const auto &road_name_empty = name_table.GetNameForID(road_name_id).empty();
const auto &required_name_empty = name_table.GetNameForID(required_name_id).empty();
if (required_name_empty && road_name_empty)
if (required_name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
return false;
return !util::guidance::requiresNameAnnounced(
required_name_id, road_name_id, name_table, street_name_suffix_table) ||
required_name_id, road_name, name_table, street_name_suffix_table) ||
!util::guidance::requiresNameAnnounced(
road_name_id, required_name_id, name_table, street_name_suffix_table);
road_name, required_name_id, name_table, street_name_suffix_table);
};
/* the beautiful way would be:
+4 -8
View File
@@ -379,15 +379,11 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
//
// 7 1
// 0
const auto &first_intersection_name_empty =
name_table.GetNameForID(first_intersection_data.name_id).empty();
const auto &second_intersection_name_empty =
name_table.GetNameForID(second_intersection_data.name_id).empty();
if (intersection[1].entry_allowed)
{
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
!second_intersection_name_empty && !first_intersection_name_empty &&
first_second_same_name)
second_intersection_data.name_id != EMPTY_NAMEID &&
first_intersection_data.name_id != EMPTY_NAMEID && first_second_same_name)
{
// circular order indicates a merge to the left (0-3 onto 4
if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) <
@@ -411,8 +407,8 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
{
BOOST_ASSERT(intersection[2].entry_allowed);
if (isMotorwayClass(intersection[2].eid, node_based_graph) &&
!second_intersection_name_empty && !first_intersection_name_empty &&
first_second_same_name)
second_intersection_data.name_id != EMPTY_NAMEID &&
first_intersection_data.name_id != EMPTY_NAMEID && first_second_same_name)
{
// circular order (5-0) onto 4
if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) <
@@ -103,12 +103,9 @@ operator()(const NodeID /*nid*/,
// ---------------------------------------------------------------------------------
SelectStraightmostRoadByNameAndOnlyChoice::SelectStraightmostRoadByNameAndOnlyChoice(
const NameID desired_name_id,
const double initial_bearing,
const bool requires_entry,
const bool stop_on_ambiguous_turns)
const NameID desired_name_id, const double initial_bearing, const bool requires_entry)
: desired_name_id(desired_name_id), initial_bearing(initial_bearing),
requires_entry(requires_entry), stop_on_ambiguous_turns(stop_on_ambiguous_turns)
requires_entry(requires_entry)
{
}
@@ -158,79 +155,24 @@ operator()(const NodeID /*nid*/,
std::min_element(std::next(std::begin(intersection)), std::end(intersection), comparator);
const auto is_valid_choice = !requires_entry || min_element->entry_allowed;
if (!is_valid_choice)
return {};
// only road exiting or continuing in the same general direction
const auto is_only_choice_with_same_name =
count_desired_name <= 2 && // <= in case we come from a bridge
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(min_element->eid).annotation_data)
.name_id == desired_name_id &&
angularDeviation(min_element->angle, STRAIGHT_ANGLE) < 100; // don't do crazy turns
const auto has_valid_angle =
((intersection.size() == 2 ||
intersection.findClosestTurn(STRAIGHT_ANGLE) == min_element) &&
angularDeviation(min_element->angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE) &&
angularDeviation(initial_bearing, min_element->bearing) < NARROW_TURN_ANGLE;
if (has_valid_angle)
// in cases where we have two edges between roads, we can have quite severe angles due to the
// random split OSRM does to break up parallel edges at any coordinate
if (!is_valid_choice || !(is_only_choice_with_same_name || has_valid_angle))
return {};
else
return (*min_element).eid;
// in some cases, stronger turns are appropriate. We allow turns of just a bit over 90 degrees,
// if it's not a end of road situation. These angles come into play where roads split into dual
// carriage-ways.
//
// e - - f
// a - - - - b
// c - - d
// |
// g
//
// is technically
//
//
// a - - - - b (ce) - - (fg)
// |
// g
const auto is_only_choice_with_same_name =
count_desired_name <= 2 && // <= in case we come from a bridge, otherwise we have a u-turn
// and the outgoing edge
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(min_element->eid).annotation_data)
.name_id == desired_name_id &&
angularDeviation(min_element->angle, STRAIGHT_ANGLE) < 100; // don't do crazy turns
// do not allow major turns in the road, if other similar turns are present
// e.g.a turn at the end of the road:
//
// a - - a - - a - b - b
// |
// a - - a
// |
// c
//
// Such a turn can never be part of a merge
// We check if there is a similar turn to the other side. If such a turn exists, we consider the
// continuation of the road not possible
if (stop_on_ambiguous_turns &&
util::angularDeviation(STRAIGHT_ANGLE, min_element->angle) > GROUP_ANGLE)
{
auto opposite = intersection.findClosestTurn(util::bearing::reverse(min_element->angle));
auto opposite_deviation = util::angularDeviation(min_element->angle, opposite->angle);
// d - - - - c - - - -e
// |
// |
// a - - - - b
// from b-c onto min_element d with opposite side e
if (opposite_deviation > (180 - FUZZY_ANGLE_DIFFERENCE))
return {};
// e
// |
// a - - - - b - - - - -d
// doing a left turn while straight is a choice
auto const best = intersection.findClosestTurn(STRAIGHT_ANGLE);
if (util::angularDeviation(best->angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
return {};
}
return is_only_choice_with_same_name ? boost::optional<EdgeID>(min_element->eid) : boost::none;
}
// ---------------------------------------------------------------------------------
@@ -295,8 +295,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
return SPECIAL_EDGEID;
}
const auto &edge_name_empty = name_table.GetNameForID(edge_data.name_id).empty();
if (!edge_name_empty)
if (EMPTY_NAMEID != edge_data.name_id)
{
const auto announce = [&](unsigned id) {
@@ -307,6 +306,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
if (std::all_of(begin(roundabout_name_ids), end(roundabout_name_ids), announce))
roundabout_name_ids.insert(edge_data.name_id);
}
continue_edge = edge_id;
}
else if (!edge.flags.roundabout && !edge.flags.circular)
+4 -10
View File
@@ -1,6 +1,5 @@
#include "extractor/guidance/sliproad_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "util/assert.hpp"
#include "util/bearing.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/name_announcements.hpp"
@@ -475,7 +474,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// Name mismatch: check roads at `c` and `d` for same name
const auto name_mismatch = [&](const NameID road_name_id) {
const auto unnamed = name_table.GetNameForID(road_name_id).empty();
const auto unnamed = road_name_id == EMPTY_NAMEID;
return unnamed ||
util::guidance::requiresNameAnnounced(road_name_id, //
@@ -500,15 +499,11 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(main_road.eid).annotation_data)
.name_id;
const auto main_road_name_empty = name_table.GetNameForID(main_road_name_id).empty();
const auto &sliproad_annotation =
node_data_container.GetAnnotation(sliproad_edge_data.annotation_data);
const auto sliproad_name_empty =
name_table.GetNameForID(sliproad_annotation.name_id).empty();
const auto candidate_road_name_empty =
name_table.GetNameForID(candidate_data.name_id).empty();
if (!sliproad_edge_data.flags.road_classification.IsLinkClass() &&
!sliproad_name_empty && !main_road_name_empty && !candidate_road_name_empty &&
sliproad_annotation.name_id != EMPTY_NAMEID && main_road_name_id != EMPTY_NAMEID &&
candidate_data.name_id != EMPTY_NAMEID &&
util::guidance::requiresNameAnnounced(main_road_name_id,
sliproad_annotation.name_id,
name_table,
@@ -580,9 +575,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
intersection[*obvious].instruction.direction_modifier =
getTurnDirection(intersection[*obvious].angle);
}
else if (!name_table.GetNameForID(main_annotation.name_id).empty())
else if (main_annotation.name_id != EMPTY_NAMEID)
{
OSRM_ASSERT(false, coordinates[intersection_node_id]);
intersection[*obvious].instruction.type = TurnType::NewName;
intersection[*obvious].instruction.direction_modifier =
getTurnDirection(intersection[*obvious].angle);
@@ -34,8 +34,7 @@ bool SuppressModeHandler::canProcess(const NodeID,
using std::end;
// travel modes for which navigation should be suppressed
static const constexpr char suppressed[] = {extractor::TRAVEL_MODE_TRAIN,
extractor::TRAVEL_MODE_FERRY};
static const constexpr char suppressed[] = {TRAVEL_MODE_TRAIN, TRAVEL_MODE_FERRY};
// If the approach way is not on the suppression blacklist, and not all the exit ways share that
// mode, there are no ways to suppress by this criteria.
+1 -14
View File
@@ -78,13 +78,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_data_container,
coordinates,
name_table,
street_name_suffix_table),
statistics_handler(intersection_generator,
node_based_graph,
node_data_container,
coordinates,
name_table,
street_name_suffix_table)
street_name_suffix_table)
{
}
@@ -181,13 +175,6 @@ Intersection TurnAnalysis::AssignTurnTypes(const NodeID node_prior_to_intersecti
road.instruction.type = TurnType::OffRamp;
});
}
// After we ran all handlers and determined instruction type
// and direction modifier gather statistics about our decisions.
if (statistics_handler.canProcess(node_prior_to_intersection, entering_via_edge, intersection))
intersection = statistics_handler(
node_prior_to_intersection, entering_via_edge, std::move(intersection));
return intersection;
}
+1 -2
View File
@@ -199,8 +199,7 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
const bool turn_is_perfectly_straight =
angularDeviation(road.angle, STRAIGHT_ANGLE) < std::numeric_limits<double>::epsilon();
const auto &via_name_empty = name_table.GetNameForID(via_data.name_id).empty();
if (!via_name_empty)
if (via_data.name_id != EMPTY_NAMEID)
{
const auto same_name = !util::guidance::requiresNameAnnounced(
via_data.name_id, road_data.name_id, name_table, street_name_suffix_table);
+20 -67
View File
@@ -4,12 +4,9 @@
#include "util/graph_loader.hpp"
#include "util/log.hpp"
#include "util/timing_util.hpp"
#include <boost/assert.hpp>
#include <set>
namespace osrm
{
namespace extractor
@@ -142,38 +139,9 @@ void NodeBasedGraphFactory::CompressGeometry()
void NodeBasedGraphFactory::CompressAnnotationData()
{
TIMER_START(compress_annotation);
/** Main idea, that we need to remove duplicated and unreferenced data
* For that:
* 1. We create set, that contains indecies of unique data items. Just create
* comparator, that compare data from annotation_data vector by passed index.
* 2. Create cached id's unordered_map, where key - stored id in set,
* value - index of item in a set from begin. We need that map, because
* std::distance(set.begin(), it) is too slow O(N). So any words in that step we reorder
* annotation data to the order it stored in a set. Apply new id's to edge data.
* 3. Remove unused anootation_data items.
* 4. At final step just need to sort result annotation_data in the same order as set.
* That makes id's stored in edge data valid.
*/
struct IndexComparator
{
IndexComparator(const std::vector<NodeBasedEdgeAnnotation> &annotation_data_)
: annotation_data(annotation_data_)
{
}
bool operator()(AnnotationID a, AnnotationID b) const
{
return annotation_data[a] < annotation_data[b];
}
private:
const std::vector<NodeBasedEdgeAnnotation> &annotation_data;
};
/** 1 */
IndexComparator comparator(annotation_data);
std::set<AnnotationID, IndexComparator> unique_annotations(comparator);
const constexpr AnnotationID INVALID_ANNOTATIONID = -1;
// remap all entries to find which are used
std::vector<AnnotationID> annotation_mapping(annotation_data.size(), INVALID_ANNOTATIONID);
// first we mark entries, by setting their mapping to 0
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
@@ -182,17 +150,22 @@ void NodeBasedGraphFactory::CompressAnnotationData()
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
auto const &edge = compressed_output_graph.GetEdgeData(nbg_edge_id);
unique_annotations.insert(edge.annotation_data);
annotation_mapping[edge.annotation_data] = 0;
}
}
// make additional map, because std::distance of std::set seems is O(N)
// that very slow
/** 2 */
AnnotationID new_id = 0;
std::unordered_map<AnnotationID, AnnotationID> cached_ids;
for (auto id : unique_annotations)
cached_ids[id] = new_id++;
// now compute a prefix sum on all entries that are 0 to find the new mapping
AnnotationID prefix_sum = 0;
for (std::size_t i = 0; i < annotation_mapping.size(); ++i)
{
if (annotation_mapping[i] == 0)
annotation_mapping[i] = prefix_sum++;
else
{
// flag for removal
annotation_data[i].name_id = INVALID_NAMEID;
}
}
// apply the mapping
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
@@ -201,24 +174,11 @@ void NodeBasedGraphFactory::CompressAnnotationData()
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
auto &edge = compressed_output_graph.GetEdgeData(nbg_edge_id);
auto const it = unique_annotations.find(edge.annotation_data);
BOOST_ASSERT(it != unique_annotations.end());
auto const it2 = cached_ids.find(*it);
BOOST_ASSERT(it2 != cached_ids.end());
edge.annotation_data = it2->second;
edge.annotation_data = annotation_mapping[edge.annotation_data];
BOOST_ASSERT(edge.annotation_data != INVALID_ANNOTATIONID);
}
}
/** 3 */
// mark unused references for remove
for (AnnotationID id = 0; id < annotation_data.size(); ++id)
{
auto const it = unique_annotations.find(id);
if (it == unique_annotations.end() || *it != id)
annotation_data[id].name_id = INVALID_NAMEID;
}
// remove unreferenced entries, shifting other entries to the front
const auto new_end =
std::remove_if(annotation_data.begin(), annotation_data.end(), [&](auto const &data) {
@@ -231,15 +191,8 @@ void NodeBasedGraphFactory::CompressAnnotationData()
const auto old_size = annotation_data.size();
// remove all remaining elements
annotation_data.erase(new_end, annotation_data.end());
// reorder data in the same order
/** 4 */
std::sort(annotation_data.begin(), annotation_data.end());
TIMER_STOP(compress_annotation);
util::Log() << " graph compression removed " << (old_size - annotation_data.size())
<< " annotations of " << old_size << " in " << TIMER_SEC(compress_annotation)
<< " seconds";
util::Log() << " graoh compression removed " << (old_size - annotation_data.size())
<< " annotations of " << old_size;
}
void NodeBasedGraphFactory::ReleaseOsmNodes()
+108 -165
View File
@@ -111,29 +111,29 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
context.state.new_enum("mode",
"inaccessible",
extractor::TRAVEL_MODE_INACCESSIBLE,
TRAVEL_MODE_INACCESSIBLE,
"driving",
extractor::TRAVEL_MODE_DRIVING,
TRAVEL_MODE_DRIVING,
"cycling",
extractor::TRAVEL_MODE_CYCLING,
TRAVEL_MODE_CYCLING,
"walking",
extractor::TRAVEL_MODE_WALKING,
TRAVEL_MODE_WALKING,
"ferry",
extractor::TRAVEL_MODE_FERRY,
TRAVEL_MODE_FERRY,
"train",
extractor::TRAVEL_MODE_TRAIN,
TRAVEL_MODE_TRAIN,
"pushing_bike",
extractor::TRAVEL_MODE_PUSHING_BIKE,
TRAVEL_MODE_PUSHING_BIKE,
"steps_up",
extractor::TRAVEL_MODE_STEPS_UP,
TRAVEL_MODE_STEPS_UP,
"steps_down",
extractor::TRAVEL_MODE_STEPS_DOWN,
TRAVEL_MODE_STEPS_DOWN,
"river_up",
extractor::TRAVEL_MODE_RIVER_UP,
TRAVEL_MODE_RIVER_UP,
"river_down",
extractor::TRAVEL_MODE_RIVER_DOWN,
TRAVEL_MODE_RIVER_DOWN,
"route",
extractor::TRAVEL_MODE_ROUTE);
TRAVEL_MODE_ROUTE);
context.state.new_enum("road_priority_class",
"motorway",
@@ -159,6 +159,80 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"connectivity",
extractor::guidance::RoadPriorityClass::CONNECTIVITY);
context.state.new_enum("turn_type",
"invalid",
extractor::guidance::TurnType::Invalid,
"new_name",
extractor::guidance::TurnType::NewName,
"continue",
extractor::guidance::TurnType::Continue,
"turn",
extractor::guidance::TurnType::Turn,
"merge",
extractor::guidance::TurnType::Merge,
"on_ramp",
extractor::guidance::TurnType::OnRamp,
"off_ramp",
extractor::guidance::TurnType::OffRamp,
"fork",
extractor::guidance::TurnType::Fork,
"end_of_road",
extractor::guidance::TurnType::EndOfRoad,
"notification",
extractor::guidance::TurnType::Notification,
"enter_roundabout",
extractor::guidance::TurnType::EnterRoundabout,
"enter_and_exit_roundabout",
extractor::guidance::TurnType::EnterAndExitRoundabout,
"enter_rotary",
extractor::guidance::TurnType::EnterRotary,
"enter_and_exit_rotary",
extractor::guidance::TurnType::EnterAndExitRotary,
"enter_roundabout_intersection",
extractor::guidance::TurnType::EnterRoundaboutIntersection,
"enter_and_exit_roundabout_intersection",
extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection,
"use_lane",
extractor::guidance::TurnType::Suppressed,
"no_turn",
extractor::guidance::TurnType::NoTurn,
"suppressed",
extractor::guidance::TurnType::Suppressed,
"enter_roundabout_at_exit",
extractor::guidance::TurnType::EnterRoundaboutAtExit,
"exit_roundabout",
extractor::guidance::TurnType::ExitRoundabout,
"enter_rotary_at_exit",
extractor::guidance::TurnType::EnterRotaryAtExit,
"exit_rotary",
extractor::guidance::TurnType::ExitRotary,
"enter_roundabout_intersection_at_exit",
extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit,
"exit_roundabout_intersection",
extractor::guidance::TurnType::ExitRoundaboutIntersection,
"stay_on_roundabout",
extractor::guidance::TurnType::StayOnRoundabout,
"sliproad",
extractor::guidance::TurnType::Sliproad);
context.state.new_enum("direction_modifier",
"u_turn",
extractor::guidance::DirectionModifier::UTurn,
"sharp_right",
extractor::guidance::DirectionModifier::SharpRight,
"right",
extractor::guidance::DirectionModifier::Right,
"slight_right",
extractor::guidance::DirectionModifier::SlightRight,
"straight",
extractor::guidance::DirectionModifier::Straight,
"slight_left",
extractor::guidance::DirectionModifier::SlightLeft,
"left",
extractor::guidance::DirectionModifier::Left,
"sharp_left",
extractor::guidance::DirectionModifier::SharpLeft);
context.state.new_enum("item_type",
"node",
osmium::item_type::node,
@@ -413,6 +487,26 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"duration",
&ExtractionSegment::duration);
context.state.new_usertype<ExtractionTurn>("ExtractionTurn",
"angle",
&ExtractionTurn::angle,
"turn_type",
&ExtractionTurn::turn_type,
"direction_modifier",
&ExtractionTurn::direction_modifier,
"has_traffic_light",
&ExtractionTurn::has_traffic_light,
"weight",
&ExtractionTurn::weight,
"duration",
&ExtractionTurn::duration,
"source_restricted",
&ExtractionTurn::source_restricted,
"target_restricted",
&ExtractionTurn::target_restricted,
"is_left_hand_driving",
&ExtractionTurn::is_left_hand_driving);
// Keep in mind .location is available only if .pbf is preprocessed to set the location with the
// ref using osmium command "osmium add-locations-to-ways"
context.state.new_usertype<osmium::NodeRef>(
@@ -559,156 +653,16 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
}
};
auto initialize_V3_extraction_turn = [&]() {
context.state.new_usertype<ExtractionTurn>(
"ExtractionTurn",
"angle",
&ExtractionTurn::angle,
"turn_type",
sol::property([](const ExtractionTurn &turn) {
if (turn.number_of_roads > 2 || turn.source_mode != turn.target_mode ||
turn.is_u_turn)
return guidance::TurnType::Turn;
else
return guidance::TurnType::NoTurn;
}),
"direction_modifier",
sol::property([](const ExtractionTurn &turn) {
if (turn.is_u_turn)
return guidance::DirectionModifier::UTurn;
else
return guidance::DirectionModifier::Straight;
}),
"has_traffic_light",
&ExtractionTurn::has_traffic_light,
"weight",
&ExtractionTurn::weight,
"duration",
&ExtractionTurn::duration,
"source_restricted",
&ExtractionTurn::source_restricted,
"target_restricted",
&ExtractionTurn::target_restricted,
"is_left_hand_driving",
&ExtractionTurn::is_left_hand_driving);
context.state.new_enum("turn_type",
"invalid",
extractor::guidance::TurnType::Invalid,
"new_name",
extractor::guidance::TurnType::NewName,
"continue",
extractor::guidance::TurnType::Continue,
"turn",
extractor::guidance::TurnType::Turn,
"merge",
extractor::guidance::TurnType::Merge,
"on_ramp",
extractor::guidance::TurnType::OnRamp,
"off_ramp",
extractor::guidance::TurnType::OffRamp,
"fork",
extractor::guidance::TurnType::Fork,
"end_of_road",
extractor::guidance::TurnType::EndOfRoad,
"notification",
extractor::guidance::TurnType::Notification,
"enter_roundabout",
extractor::guidance::TurnType::EnterRoundabout,
"enter_and_exit_roundabout",
extractor::guidance::TurnType::EnterAndExitRoundabout,
"enter_rotary",
extractor::guidance::TurnType::EnterRotary,
"enter_and_exit_rotary",
extractor::guidance::TurnType::EnterAndExitRotary,
"enter_roundabout_intersection",
extractor::guidance::TurnType::EnterRoundaboutIntersection,
"enter_and_exit_roundabout_intersection",
extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection,
"use_lane",
extractor::guidance::TurnType::Suppressed,
"no_turn",
extractor::guidance::TurnType::NoTurn,
"suppressed",
extractor::guidance::TurnType::Suppressed,
"enter_roundabout_at_exit",
extractor::guidance::TurnType::EnterRoundaboutAtExit,
"exit_roundabout",
extractor::guidance::TurnType::ExitRoundabout,
"enter_rotary_at_exit",
extractor::guidance::TurnType::EnterRotaryAtExit,
"exit_rotary",
extractor::guidance::TurnType::ExitRotary,
"enter_roundabout_intersection_at_exit",
extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit,
"exit_roundabout_intersection",
extractor::guidance::TurnType::ExitRoundaboutIntersection,
"stay_on_roundabout",
extractor::guidance::TurnType::StayOnRoundabout,
"sliproad",
extractor::guidance::TurnType::Sliproad);
context.state.new_enum("direction_modifier",
"u_turn",
extractor::guidance::DirectionModifier::UTurn,
"sharp_right",
extractor::guidance::DirectionModifier::SharpRight,
"right",
extractor::guidance::DirectionModifier::Right,
"slight_right",
extractor::guidance::DirectionModifier::SlightRight,
"straight",
extractor::guidance::DirectionModifier::Straight,
"slight_left",
extractor::guidance::DirectionModifier::SlightLeft,
"left",
extractor::guidance::DirectionModifier::Left,
"sharp_left",
extractor::guidance::DirectionModifier::SharpLeft);
};
switch (context.api_version)
{
case 4:
{
context.state.new_usertype<ExtractionTurn>("ExtractionTurn",
"angle",
&ExtractionTurn::angle,
"number_of_roads",
&ExtractionTurn::number_of_roads,
"is_u_turn",
&ExtractionTurn::is_u_turn,
"has_traffic_light",
&ExtractionTurn::has_traffic_light,
"weight",
&ExtractionTurn::weight,
"duration",
&ExtractionTurn::duration,
"source_restricted",
&ExtractionTurn::source_restricted,
"target_restricted",
&ExtractionTurn::target_restricted,
"is_left_hand_driving",
&ExtractionTurn::is_left_hand_driving,
"source_mode",
&ExtractionTurn::source_mode,
"target_mode",
&ExtractionTurn::target_mode);
initV2Context();
break;
}
case 3:
case 2:
{
initialize_V3_extraction_turn();
initV2Context();
break;
}
case 1:
{
initialize_V3_extraction_turn();
// cache references to functions for faster execution
context.turn_function = context.state["turn_function"];
context.node_function = context.state["node_function"];
@@ -739,8 +693,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
break;
}
case 0:
initialize_V3_extraction_turn();
// cache references to functions for faster execution
context.turn_function = context.state["turn_function"];
context.node_function = context.state["node_function"];
@@ -899,7 +851,6 @@ std::vector<std::vector<std::string>> Sol2ScriptingEnvironment::GetExcludableCla
auto &context = GetSol2Context();
switch (context.api_version)
{
case 4:
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListsFromTable("excludable");
@@ -913,7 +864,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetClassNames()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 4:
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("classes");
@@ -927,7 +877,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 4:
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list");
@@ -943,7 +892,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 4:
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions");
@@ -959,7 +907,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetRelations()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 4:
case 3:
return Sol2ScriptingEnvironment::GetStringListFromTable("relation_types");
default:
@@ -973,7 +920,6 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
switch (context.api_version)
{
case 4:
case 3:
case 2:
if (context.has_turn_penalty_function)
@@ -1005,14 +951,14 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
case 0:
if (context.has_turn_penalty_function)
{
if (turn.number_of_roads > 2)
if (turn.turn_type != guidance::TurnType::NoTurn)
{
// Get turn duration and convert deci-seconds to seconds
turn.duration = static_cast<double>(context.turn_function(turn.angle)) / 10.;
BOOST_ASSERT(turn.weight == 0);
// add U-turn penalty
if (turn.is_u_turn)
if (turn.direction_modifier == guidance::DirectionModifier::UTurn)
turn.duration += context.properties.GetUturnPenalty();
}
else
@@ -1041,7 +987,6 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
{
switch (context.api_version)
{
case 4:
case 3:
case 2:
context.segment_function(context.profile_table, segment);
@@ -1066,7 +1011,6 @@ void LuaScriptingContext::ProcessNode(const osmium::Node &node,
switch (api_version)
{
case 4:
case 3:
node_function(profile_table, node, result, relations);
break;
@@ -1088,7 +1032,6 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way,
switch (api_version)
{
case 4:
case 3:
way_function(profile_table, way, result, relations);
break;
+37
View File
@@ -331,6 +331,43 @@ void Storage::PopulateLayout(DataLayout &layout)
layout.SetBlockSize<char>(DataLayout::TIMESTAMP, timestamp_size);
}
// load core marker size
if (boost::filesystem::exists(config.GetPath(".osrm.core")))
{
io::FileReader core_marker_file(config.GetPath(".osrm.core"),
io::FileReader::VerifyFingerprint);
const auto num_metrics = core_marker_file.ReadElementCount64();
if (num_metrics > NUM_METRICS)
{
throw util::exception("Only " + std::to_string(NUM_METRICS) +
" metrics are supported at the same time.");
}
const auto number_of_core_markers = core_marker_file.ReadElementCount64();
for (const auto index : util::irange<std::size_t>(0, num_metrics))
{
layout.SetBlockSize<unsigned>(
static_cast<DataLayout::BlockID>(DataLayout::CH_CORE_MARKER_0 + index),
number_of_core_markers);
}
for (const auto index : util::irange<std::size_t>(num_metrics, NUM_METRICS))
{
layout.SetBlockSize<unsigned>(
static_cast<DataLayout::BlockID>(DataLayout::CH_CORE_MARKER_0 + index), 0);
}
}
else
{
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_0, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_1, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_2, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_3, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_4, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_5, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_6, 0);
layout.SetBlockSize<unsigned>(DataLayout::CH_CORE_MARKER_7, 0);
}
// load turn weight penalties
{
io::FileReader turn_weight_penalties_file(config.GetPath(".osrm.turn_weight_penalties"),
+1 -1
View File
@@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956],
exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2)
exports.test_tile = {'at': [17059, 11948, 15], 'size': 168606};
exports.test_tile = {'at': [17059, 11948, 15], 'size': 167166};
// Test files generated by the routing engine; check test/data
-5
View File
@@ -1,5 +1,3 @@
#include "extractor/travel_mode.hpp"
#include "engine/guidance/assemble_geometry.hpp"
#include "engine/guidance/assemble_leg.hpp"
#include "engine/guidance/assemble_overview.hpp"
@@ -14,7 +12,6 @@ BOOST_AUTO_TEST_SUITE(guidance_assembly)
BOOST_AUTO_TEST_CASE(trim_short_segments)
{
using namespace osrm::extractor;
using namespace osrm::extractor::guidance;
using namespace osrm::engine::guidance;
using namespace osrm::engine;
@@ -39,7 +36,6 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
// Check that duplicated coordinate in the end is removed
std::vector<RouteStep> steps = {{324,
false,
"Central Park West",
"",
"",
@@ -61,7 +57,6 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
3,
{intersection1}},
{324,
false,
"Central Park West",
"",
"",
-1
View File
@@ -1,5 +1,4 @@
#include "engine/api/json_factory.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
+1 -2
View File
@@ -216,7 +216,7 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
extractor::TravelMode GetTravelMode(const NodeID /*id*/) const override
{
return extractor::TRAVEL_MODE_DRIVING;
return TRAVEL_MODE_DRIVING;
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate /*south_west*/,
@@ -366,7 +366,6 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
util::guidance::EntryClass GetEntryClass(const EdgeID /*turn_id*/) const override { return {}; }
bool IsLeftHandDriving(const NodeID /*id*/) const override { return false; }
bool IsSegregated(const NodeID /*id*/) const override { return false; }
};
} // datafacade
-5
View File
@@ -105,11 +105,6 @@ BOOST_AUTO_TEST_CASE(test_nearest_response_for_location_in_small_component)
// Nearest service should snap to road network without considering components.
const auto distance = waypoint_object.values.at("distance").get<json::Number>().value;
BOOST_CHECK_LT(distance, 20);
const auto &nodes = waypoint_object.values.at("nodes").get<json::Array>().values;
BOOST_CHECK(nodes.size() == 2);
BOOST_CHECK(nodes[0].get<util::json::Number>().value != 0);
BOOST_CHECK(nodes[1].get<util::json::Number>().value != 0);
}
}
-2
View File
@@ -64,7 +64,6 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{"geometry", "yw_jGupkl@??"},
{"name", "Boulevard du Larvotto"},
{"mode", "driving"},
{"driving_side", "right"},
{"maneuver",
json::Object{{
{"location", location},
@@ -85,7 +84,6 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{"geometry", "yw_jGupkl@"},
{"name", "Boulevard du Larvotto"},
{"mode", "driving"},
{"driving_side", "right"},
{"maneuver",
json::Object{{{"location", location},
{"bearing_before", 58},

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