Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29ce651493 | |||
| 1b53b90eec | |||
| 5f84032261 | |||
| 9c73e42f5f | |||
| c638499c0f | |||
| 7c5977daf6 | |||
| 253522c406 | |||
| 1e2d3882d1 | |||
| fd43586b60 | |||
| fd13ffe7ba |
@@ -1,2 +0,0 @@
|
||||
test
|
||||
build
|
||||
+2
-50
@@ -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
|
||||
|
||||
+2
-57
@@ -1,65 +1,10 @@
|
||||
# 5.14.3
|
||||
- Changes from 5.14.2:
|
||||
- Bugfixes:
|
||||
- FIXED #4754: U-Turn penalties are applied to straight turns.
|
||||
- FIXED #4756: Removed too restrictive road name check in the sliproad handler
|
||||
- FIXED #4731: Use correct weights for edge-based graph duplicated via nodes.
|
||||
- Profile:
|
||||
- CHANGED: added Belarus speed limits
|
||||
- CHANGED: set default urban speed in Ukraine to 50kmh
|
||||
|
||||
# 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
|
||||
- Node.js Bindings:
|
||||
- ADDED: Exposed new `max_radiuses_map_matching` option from `EngingConfig` options
|
||||
- Tools:
|
||||
- ADDED: New osrm-routed `max_radiuses_map_matching` command line flag to optionally set a maximum radius for map matching
|
||||
|
||||
# 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 RC2
|
||||
- Changes from 5.12:
|
||||
- Profile:
|
||||
- Append cardinal directions from route relations to ref fields to improve instructions; off by default see `profile.cardinal_directions`
|
||||
- Append cardinal directions from route relations to ref fields to improve instructions
|
||||
- Support of `distance` weight in foot and bicycle profiles
|
||||
- Support of relations processing
|
||||
- Added `way:get_location_tag(key)` method to get location-dependent tags https://github.com/Project-OSRM/osrm-backend/wiki/Using-location-dependent-data-in-profiles
|
||||
- Added `forward_ref` and `backward_ref` support
|
||||
- Left-side driving mode is specified by a local Boolean flag `is_left_hand_driving` in `ExtractionWay` and `ExtractionTurn`
|
||||
- Support literal values for maxspeeds in NO, PL and ZA
|
||||
- Infrastructure:
|
||||
|
||||
+3
-3
@@ -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 3)
|
||||
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(
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Code of conduct
|
||||
|
||||
Everyone is invited to participate in Project OSRM’s 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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 |
|
||||
|
||||
+39
-40
@@ -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,33 +147,31 @@ 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?
|
||||
name | String | Name of the way
|
||||
ref | String | Road number (equal to set `forward_ref` and `backward_ref` with one value)
|
||||
forward_ref | String | Road number in forward way direction
|
||||
backward_ref | String | Road number in backward way direction
|
||||
ref | String | Road number
|
||||
destinations | String | The road's destinations
|
||||
exits | String | The ramp's exit numbers or names
|
||||
pronunciation | String | Name pronunciation
|
||||
@@ -187,18 +186,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 +229,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 +282,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
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ Feature: Barriers
|
||||
| | x |
|
||||
| bollard | x |
|
||||
| gate | x |
|
||||
| lift_gate | x |
|
||||
| cycle_barrier | x |
|
||||
| cattle_grid | x |
|
||||
| border_control | x |
|
||||
|
||||
@@ -157,16 +157,15 @@ Feature: Car - Restricted access
|
||||
|
||||
Scenario: Car - Access combinations
|
||||
Then routability should be
|
||||
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
|
||||
| runway | private | | | permissive | x | x | |
|
||||
| primary | forestry | | yes | | x | x | |
|
||||
| cycleway | | | designated | | x | x | |
|
||||
| unclassified | | | destination | destination | x | x | |
|
||||
| residential | | yes | no | | | | |
|
||||
| motorway | yes | permissive | | private | x | | implied oneway |
|
||||
| trunk | agricultural | designated | permissive | no | | | |
|
||||
| pedestrian | | | | | | | |
|
||||
| pedestrian | | | | destination | | | temporary disabled #3773 |
|
||||
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
|
||||
| runway | private | | | permissive | x | x | |
|
||||
| primary | forestry | | yes | | x | x | |
|
||||
| cycleway | | | designated | | x | x | |
|
||||
| residential | | yes | no | | | | |
|
||||
| motorway | yes | permissive | | private | x | | implied oneway |
|
||||
| trunk | agricultural | designated | permissive | no | | | |
|
||||
| pedestrian | | | | | | | |
|
||||
| pedestrian | | | | destination | | | temporary disabled #3773 |
|
||||
|
||||
Scenario: Car - Ignore access tags for other modes
|
||||
Then routability should be
|
||||
|
||||
+10
-10
@@ -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 |
|
||||
|
||||
@@ -4,11 +4,6 @@ Feature: Car - route relations
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Assignment using relation membership roles
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -31,63 +26,7 @@ Feature: Car - route relations
|
||||
| b,a | westbound,westbound | I 80 $west,I 80 $west |
|
||||
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
|
||||
|
||||
Scenario: No cardinal directions by default
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = false
|
||||
"""
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
c----------------d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | highway | ref |
|
||||
| ba | westbound | motorway | I 80 |
|
||||
| cd | eastbound | motorway | I 80;CO 93 |
|
||||
|
||||
And the relations
|
||||
| type | way:east | way:west | route | ref | network |
|
||||
| route | cd | ba | road | 80 | US:I |
|
||||
| route | cd | ba | road | 93 | US:CO |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | ref |
|
||||
| b,a | westbound,westbound | I 80,I 80 |
|
||||
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
|
||||
|
||||
Scenario: No cardinal directions by default
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
c----------------d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | highway | ref |
|
||||
| ba | westbound | motorway | I 80 |
|
||||
| cd | eastbound | motorway | I 80;CO 93 |
|
||||
|
||||
And the relations
|
||||
| type | way:east | way:west | route | ref | network |
|
||||
| route | cd | ba | road | 80 | US:I |
|
||||
| route | cd | ba | road | 93 | US:CO |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | ref |
|
||||
| b,a | westbound,westbound | I 80,I 80 |
|
||||
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
|
||||
|
||||
|
||||
Scenario: Assignment using relation direction property (no role on members)
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -112,11 +51,6 @@ Feature: Car - route relations
|
||||
|
||||
|
||||
Scenario: Forward assignment on one-way roads using relation direction property
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -140,41 +74,31 @@ Feature: Car - route relations
|
||||
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
|
||||
|
||||
|
||||
Scenario: Forward/backward assignment on non-divided roads with role direction tag
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | highway | ref | oneway |
|
||||
| ab | mainroad | motorway | I 80 | no |
|
||||
|
||||
And the relations
|
||||
| type | direction | way:forward | route | ref | network |
|
||||
| route | west | ab | road | 80 | US:I |
|
||||
|
||||
And the relations
|
||||
| type | direction | way:backward | route | ref | network |
|
||||
| route | east | ab | road | 80 | US:I |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | ref |
|
||||
| a,b | mainroad,mainroad | I 80 $west,I 80 $west |
|
||||
| b,a | mainroad,mainroad | I 80 $east,I 80 $east |
|
||||
# Scenario: Forward/backward assignment on non-divided roads with role direction tag
|
||||
# Given the node map
|
||||
# """
|
||||
# a----------------b
|
||||
# """
|
||||
#
|
||||
# And the ways
|
||||
# | nodes | name | highway | ref | oneway |
|
||||
# | ab | mainroad | motorway | I 80 | no |
|
||||
#
|
||||
# And the relations
|
||||
# | type | direction | way:forward | route | ref | network |
|
||||
# | route | west | ab | road | 80 | US:I |
|
||||
#
|
||||
# And the relations
|
||||
# | type | direction | way:backward | route | ref | network |
|
||||
# | route | east | ab | road | 80 | US:I |
|
||||
#
|
||||
# When I route I should get
|
||||
# | waypoints | route | ref |
|
||||
# | b,a | mainroad,mainroad | I 80 $west,I 80 $west |
|
||||
# | a,b | mainroad,mainroad | I 80 $east,I 80 $east |
|
||||
|
||||
|
||||
Scenario: Conflict between role and direction
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -194,11 +118,6 @@ Feature: Car - route relations
|
||||
|
||||
|
||||
Scenario: Conflict between role and superrelation direction
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -221,11 +140,6 @@ Feature: Car - route relations
|
||||
| a,b | eastbound,eastbound | I 80,I 80 |
|
||||
|
||||
Scenario: Conflict between role and superrelation role
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -248,11 +162,6 @@ Feature: Car - route relations
|
||||
| a,b | eastbound,eastbound | I 80,I 80 |
|
||||
|
||||
Scenario: Direction only available via superrelation role
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -275,11 +184,6 @@ Feature: Car - route relations
|
||||
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
|
||||
|
||||
Scenario: Direction only available via superrelation direction
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.cardinal_directions = true
|
||||
"""
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a----------------b
|
||||
@@ -301,7 +205,6 @@ Feature: Car - route relations
|
||||
| waypoints | route | ref |
|
||||
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
|
||||
|
||||
|
||||
# Scenario: Three levels of indirection
|
||||
# Given the node map
|
||||
# """
|
||||
@@ -326,4 +229,4 @@ Feature: Car - route relations
|
||||
#
|
||||
# When I route I should get
|
||||
# | waypoints | route | ref |
|
||||
# | a,b | eastbound,eastbound | I 80 $east,I 80 $east |
|
||||
# | a,b | eastbound,eastbound | I 80 $east,I 80 $east |
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,7 +10,6 @@ Feature: Barriers
|
||||
| | x |
|
||||
| bollard | x |
|
||||
| gate | x |
|
||||
| lift_gate | x |
|
||||
| cycle_barrier | x |
|
||||
| cattle_grid | x |
|
||||
| border_control | x |
|
||||
|
||||
@@ -47,7 +47,7 @@ Feature: Turn Lane Guidance
|
||||
e
|
||||
a . . b . . . c g
|
||||
` .
|
||||
` .
|
||||
` .
|
||||
` d
|
||||
f
|
||||
"""
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -992,6 +992,7 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| dbef | primary | dbef | |
|
||||
| ae | primary_link | ae | yes |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
|
||||
@@ -1018,6 +1019,7 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| dbcf | primary | dbcf | |
|
||||
| ac | primary_link | ae | yes |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sab,dbcf,dbcf | depart,turn right,arrive | s,a,f |
|
||||
@@ -1045,55 +1047,7 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| ae | primary_link | sab | yes |
|
||||
| cg | primary | cg | |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sab,dbcef,dbcef | depart,turn right,arrive | s,a,f |
|
||||
|
||||
|
||||
@sliproads
|
||||
Scenario: Sliproad converted from a fork
|
||||
Given the node map
|
||||
"""
|
||||
d
|
||||
.
|
||||
b
|
||||
s . a '.
|
||||
`c
|
||||
.
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | ref | oneway |
|
||||
| sa | tertiary | | D 60A | yes |
|
||||
| ab | tertiary | ab | D 60A | yes |
|
||||
| ac | tertiary | | D 60A | yes |
|
||||
| dbcf | tertiary | dbcf | D 543 | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | ,dbcf,dbcf | depart,turn right,arrive | s,a,f |
|
||||
|
||||
|
||||
@sliproads
|
||||
Scenario: Sliproad to a road with a reference only
|
||||
Given the node map
|
||||
"""
|
||||
s . a . b . d
|
||||
` .
|
||||
' .
|
||||
..
|
||||
c
|
||||
.
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | ref | oneway |
|
||||
| sabd | primary | road | | |
|
||||
| bcf | primary | | K108 | |
|
||||
| ac | primary_link | | | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | road,, | depart,turn right,arrive | s,a,f |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -745,15 +745,12 @@ Feature: Basic Roundabout
|
||||
|
||||
|
||||
Scenario: Drive through roundabout
|
||||
Given a grid size of 5 meters
|
||||
Given the node map
|
||||
"""
|
||||
. a .
|
||||
. .
|
||||
b e --- d ---- f
|
||||
. .
|
||||
.c.
|
||||
g h
|
||||
a
|
||||
b e d f
|
||||
c
|
||||
g h
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@@ -763,12 +760,12 @@ Feature: Basic Roundabout
|
||||
| gch | | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | bearings | route | turns |
|
||||
| e,f | 90 90 | edf,edf | depart,arrive |
|
||||
| e,h | 90 130 | edf,gch,gch,gch | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||
| g,f | 50 90 | gch,edf,edf,edf | depart,roundabout-exit-2,exit roundabout slight right,arrive |
|
||||
| g,h | 50 130 | gch,gch,gch | depart,exit roundabout right,arrive |
|
||||
| e,e | 90 270 | edf,edf,edf,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
|
||||
| waypoints | bearings | route | turns |
|
||||
| e,f | 90 90 | edf,edf | depart,arrive |
|
||||
| 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,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
|
||||
|
||||
Scenario: CCW and CW roundabouts with overlaps
|
||||
Given the node map
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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(',') + ']');
|
||||
};
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -81,8 +81,6 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
|
||||
auto filtered_core_graph =
|
||||
shared_core_graph.Filter([&filter](const NodeID node) { return filter[node]; });
|
||||
|
||||
contractGraph(filtered_core_graph, is_shared_core, is_shared_core, node_weights);
|
||||
|
||||
edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,16 +47,15 @@ struct ExtractionWay
|
||||
duration = -1;
|
||||
weight = -1;
|
||||
name.clear();
|
||||
forward_ref.clear();
|
||||
backward_ref.clear();
|
||||
ref.clear();
|
||||
pronunciation.clear();
|
||||
destinations.clear();
|
||||
exits.clear();
|
||||
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;
|
||||
@@ -68,10 +67,8 @@ struct ExtractionWay
|
||||
// wrappers to allow assigning nil (nullptr) to string values
|
||||
void SetName(const char *value) { detail::maybeSetString(name, value); }
|
||||
const char *GetName() const { return name.c_str(); }
|
||||
void SetForwardRef(const char *value) { detail::maybeSetString(forward_ref, value); }
|
||||
const char *GetForwardRef() const { return forward_ref.c_str(); }
|
||||
void SetBackwardRef(const char *value) { detail::maybeSetString(backward_ref, value); }
|
||||
const char *GetBackwardRef() const { return backward_ref.c_str(); }
|
||||
void SetRef(const char *value) { detail::maybeSetString(ref, value); }
|
||||
const char *GetRef() const { return ref.c_str(); }
|
||||
void SetDestinations(const char *value) { detail::maybeSetString(destinations, value); }
|
||||
const char *GetDestinations() const { return destinations.c_str(); }
|
||||
void SetExits(const char *value) { detail::maybeSetString(exits, value); }
|
||||
@@ -104,16 +101,15 @@ struct ExtractionWay
|
||||
// weight of the whole way in both directions
|
||||
double weight;
|
||||
std::string name;
|
||||
std::string forward_ref;
|
||||
std::string backward_ref;
|
||||
std::string ref;
|
||||
std::string pronunciation;
|
||||
std::string destinations;
|
||||
std::string exits;
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ class ExtractorCallbacks
|
||||
// actually maps to name ids
|
||||
using MapKey = std::tuple<std::string, std::string, std::string, std::string, std::string>;
|
||||
using MapVal = unsigned;
|
||||
using StringMap = std::unordered_map<MapKey, MapVal>;
|
||||
StringMap string_map;
|
||||
std::unordered_map<MapKey, MapVal> string_map;
|
||||
ExtractionContainers &external_memory;
|
||||
std::unordered_map<std::string, ClassData> &classes_map;
|
||||
guidance::LaneDescriptionMap &lane_description_map;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -77,11 +77,7 @@ struct TurnInstruction
|
||||
|
||||
TurnType::Enum type : 5;
|
||||
DirectionModifier::Enum direction_modifier : 3;
|
||||
|
||||
bool IsUTurn() const
|
||||
{
|
||||
return type != TurnType::NoTurn && direction_modifier == DirectionModifier::UTurn;
|
||||
}
|
||||
// the lane tupel that is used for the turn
|
||||
|
||||
static TurnInstruction INVALID() { return {TurnType::Invalid, DirectionModifier::UTurn}; }
|
||||
|
||||
@@ -313,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"})
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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) << " "
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,8 +26,7 @@ namespace guidance
|
||||
// Name Change Logic
|
||||
// Used both during Extraction as well as during Post-Processing
|
||||
|
||||
inline util::StringView longest_common_substring(const util::StringView &lhs,
|
||||
const util::StringView &rhs)
|
||||
inline std::string longest_common_substring(const std::string &lhs, const std::string &rhs)
|
||||
{
|
||||
if (lhs.empty() || rhs.empty())
|
||||
return "";
|
||||
@@ -61,15 +60,15 @@ inline util::StringView longest_common_substring(const util::StringView &lhs,
|
||||
|
||||
// TODO US-ASCII support only, no UTF-8 support
|
||||
// While UTF-8 might work in some cases, we do not guarantee full functionality
|
||||
template <typename StringView> inline auto decompose(const StringView &lhs, const StringView &rhs)
|
||||
inline auto decompose(const std::string &lhs, const std::string &rhs)
|
||||
{
|
||||
auto const lcs = longest_common_substring(lhs, rhs);
|
||||
|
||||
// trim spaces, transform to lower
|
||||
const auto trim = [](StringView view) {
|
||||
const auto trim = [](auto str) {
|
||||
// we compare suffixes based on this value, it might break UTF chars, but as long as we are
|
||||
// consistent in handling, we do not create bad results
|
||||
std::string str = boost::to_lower_copy(view.to_string());
|
||||
boost::to_lower(str);
|
||||
auto front = str.find_first_not_of(" ");
|
||||
|
||||
if (front == std::string::npos)
|
||||
@@ -81,7 +80,8 @@ template <typename StringView> inline auto decompose(const StringView &lhs, cons
|
||||
|
||||
if (lcs.empty())
|
||||
{
|
||||
return std::make_tuple(trim(lhs), trim(rhs), std::string(), std::string());
|
||||
std::string empty = "";
|
||||
return std::make_tuple(trim(lhs), trim(rhs), empty, empty);
|
||||
}
|
||||
|
||||
// find the common substring in both
|
||||
@@ -92,27 +92,32 @@ template <typename StringView> inline auto decompose(const StringView &lhs, cons
|
||||
BOOST_ASSERT(rhs_pos + lcs.size() <= rhs.size());
|
||||
|
||||
// prefixes
|
||||
auto lhs_prefix = (lhs_pos > 0) ? lhs.substr(0, lhs_pos) : StringView();
|
||||
auto rhs_prefix = (rhs_pos > 0) ? rhs.substr(0, rhs_pos) : StringView();
|
||||
std::string lhs_prefix = (lhs_pos > 0) ? lhs.substr(0, lhs_pos) : "";
|
||||
std::string rhs_prefix = (rhs_pos > 0) ? rhs.substr(0, rhs_pos) : "";
|
||||
|
||||
// suffices
|
||||
auto lhs_suffix = lhs.substr(lhs_pos + lcs.size());
|
||||
auto rhs_suffix = rhs.substr(rhs_pos + lcs.size());
|
||||
std::string lhs_suffix = lhs.substr(lhs_pos + lcs.size());
|
||||
std::string rhs_suffix = rhs.substr(rhs_pos + lcs.size());
|
||||
|
||||
return std::make_tuple(trim(lhs_prefix), trim(lhs_suffix), trim(rhs_prefix), trim(rhs_suffix));
|
||||
lhs_prefix = trim(std::move(lhs_prefix));
|
||||
lhs_suffix = trim(std::move(lhs_suffix));
|
||||
rhs_prefix = trim(std::move(rhs_prefix));
|
||||
rhs_suffix = trim(std::move(rhs_suffix));
|
||||
|
||||
return std::make_tuple(lhs_prefix, lhs_suffix, rhs_prefix, rhs_suffix);
|
||||
}
|
||||
|
||||
// Note: there is an overload without suffix checking below.
|
||||
// (that's the reason we template the suffix table here)
|
||||
template <typename StringView, typename SuffixTable>
|
||||
inline bool requiresNameAnnounced(const StringView &from_name,
|
||||
const StringView &from_ref,
|
||||
const StringView &from_pronunciation,
|
||||
const StringView &from_exits,
|
||||
const StringView &to_name,
|
||||
const StringView &to_ref,
|
||||
const StringView &to_pronunciation,
|
||||
const StringView &to_exits,
|
||||
template <typename SuffixTable>
|
||||
inline bool requiresNameAnnounced(const std::string &from_name,
|
||||
const std::string &from_ref,
|
||||
const std::string &from_pronunciation,
|
||||
const std::string &from_exits,
|
||||
const std::string &to_name,
|
||||
const std::string &to_ref,
|
||||
const std::string &to_pronunciation,
|
||||
const std::string &to_exits,
|
||||
const SuffixTable &suffix_table)
|
||||
{
|
||||
// first is empty and the second is not
|
||||
@@ -129,7 +134,7 @@ inline bool requiresNameAnnounced(const StringView &from_name,
|
||||
boost::starts_with(from_name, to_name) || boost::starts_with(to_name, from_name);
|
||||
|
||||
const auto checkForPrefixOrSuffixChange =
|
||||
[](const StringView &first, const StringView &second, const SuffixTable &suffix_table) {
|
||||
[](const std::string &first, const std::string &second, const SuffixTable &suffix_table) {
|
||||
std::string first_prefix, first_suffix, second_prefix, second_suffix;
|
||||
std::tie(first_prefix, first_suffix, second_prefix, second_suffix) =
|
||||
decompose(first, second);
|
||||
@@ -198,17 +203,17 @@ inline bool requiresNameAnnounced(const std::string &from_name,
|
||||
struct NopSuffixTable final
|
||||
{
|
||||
NopSuffixTable() {}
|
||||
bool isSuffix(const StringView &) const { return false; }
|
||||
bool isSuffix(const std::string &) const { return false; }
|
||||
} static const table;
|
||||
|
||||
return requiresNameAnnounced(util::StringView(from_name),
|
||||
util::StringView(from_ref),
|
||||
util::StringView(from_pronunciation),
|
||||
util::StringView(from_exits),
|
||||
util::StringView(to_name),
|
||||
util::StringView(to_ref),
|
||||
util::StringView(to_pronunciation),
|
||||
util::StringView(to_exits),
|
||||
return requiresNameAnnounced(from_name,
|
||||
from_ref,
|
||||
from_pronunciation,
|
||||
from_exits,
|
||||
to_name,
|
||||
to_ref,
|
||||
to_pronunciation,
|
||||
to_exits,
|
||||
table);
|
||||
}
|
||||
|
||||
@@ -220,17 +225,37 @@ inline bool requiresNameAnnounced(const NameID from_name_id,
|
||||
if (from_name_id == to_name_id)
|
||||
return false;
|
||||
else
|
||||
return requiresNameAnnounced(name_table.GetNameForID(from_name_id),
|
||||
name_table.GetRefForID(from_name_id),
|
||||
name_table.GetPronunciationForID(from_name_id),
|
||||
name_table.GetExitsForID(from_name_id),
|
||||
return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(),
|
||||
name_table.GetRefForID(from_name_id).to_string(),
|
||||
name_table.GetPronunciationForID(from_name_id).to_string(),
|
||||
name_table.GetExitsForID(from_name_id).to_string(),
|
||||
//
|
||||
name_table.GetNameForID(to_name_id),
|
||||
name_table.GetRefForID(to_name_id),
|
||||
name_table.GetPronunciationForID(to_name_id),
|
||||
name_table.GetExitsForID(to_name_id),
|
||||
name_table.GetNameForID(to_name_id).to_string(),
|
||||
name_table.GetRefForID(to_name_id).to_string(),
|
||||
name_table.GetPronunciationForID(to_name_id).to_string(),
|
||||
name_table.GetExitsForID(to_name_id).to_string(),
|
||||
//
|
||||
suffix_table);
|
||||
// FIXME: converts StringViews to strings since the name change heuristics mutates in place
|
||||
}
|
||||
|
||||
inline bool requiresNameAnnounced(const NameID from_name_id,
|
||||
const NameID to_name_id,
|
||||
const util::NameTable &name_table)
|
||||
{
|
||||
if (from_name_id == to_name_id)
|
||||
return false;
|
||||
else
|
||||
return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(),
|
||||
name_table.GetRefForID(from_name_id).to_string(),
|
||||
name_table.GetPronunciationForID(from_name_id).to_string(),
|
||||
name_table.GetExitsForID(from_name_id).to_string(),
|
||||
//
|
||||
name_table.GetNameForID(to_name_id).to_string(),
|
||||
name_table.GetRefForID(to_name_id).to_string(),
|
||||
name_table.GetExitsForID(to_name_id).to_string(),
|
||||
name_table.GetPronunciationForID(to_name_id).to_string());
|
||||
// FIXME: converts StringViews to strings since the name change heuristics mutates in place
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
Generated
+94
-94
@@ -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
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.14.3",
|
||||
"version": "5.13.0-rc.2",
|
||||
"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": {
|
||||
|
||||
@@ -48,7 +48,6 @@ function setup()
|
||||
'toll_booth',
|
||||
'sally_port',
|
||||
'gate',
|
||||
'lift_gate',
|
||||
'no',
|
||||
'block'
|
||||
},
|
||||
|
||||
+32
-9
@@ -1,6 +1,6 @@
|
||||
-- Car profile
|
||||
|
||||
api_version = 4
|
||||
api_version = 3
|
||||
|
||||
Set = require('lib/set')
|
||||
Sequence = require('lib/sequence')
|
||||
@@ -35,7 +35,6 @@ function setup()
|
||||
turn_penalty = 7.5,
|
||||
speed_reduction = 0.8,
|
||||
turn_bias = 1.075,
|
||||
cardinal_directions = false,
|
||||
|
||||
-- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other
|
||||
suffix_list = {
|
||||
@@ -162,7 +161,6 @@ function setup()
|
||||
'tertiary_link',
|
||||
'residential',
|
||||
'living_street',
|
||||
'unclassified'
|
||||
},
|
||||
|
||||
construction_whitelist = Set {
|
||||
@@ -253,8 +251,6 @@ function setup()
|
||||
["at:rural"] = 100,
|
||||
["at:trunk"] = 100,
|
||||
["be:motorway"] = 120,
|
||||
["by:urban"] = 60,
|
||||
["by:motorway"] = 110,
|
||||
["ch:rural"] = 80,
|
||||
["ch:trunk"] = 100,
|
||||
["ch:motorway"] = 120,
|
||||
@@ -278,6 +274,7 @@ function setup()
|
||||
["ru:living_street"] = 20,
|
||||
["ru:urban"] = 60,
|
||||
["ru:motorway"] = 110,
|
||||
["ua:urban"] = 60,
|
||||
["uk:nsl_single"] = (60*1609)/1000,
|
||||
["uk:nsl_dual"] = (70*1609)/1000,
|
||||
["uk:motorway"] = (70*1609)/1000,
|
||||
@@ -405,8 +402,34 @@ function process_way(profile, way, result, relations)
|
||||
|
||||
WayHandlers.run(profile, way, result, data, handlers, relations)
|
||||
|
||||
if profile.cardinal_directions then
|
||||
Relations.process_way_refs(way, relations, result)
|
||||
local parsed_rel_list = {}
|
||||
local rel_id_list = relations:get_relations(way)
|
||||
for i, rel_id in ipairs(rel_id_list) do
|
||||
local rel = relations:relation(rel_id)
|
||||
parsed_rel_list[i] = Relations.parse_route_relation(rel, way, relations)
|
||||
end
|
||||
|
||||
-- now process relations data
|
||||
local matched_refs = nil;
|
||||
if result.ref then
|
||||
local match_res = Relations.match_to_ref(parsed_rel_list, result.ref)
|
||||
|
||||
local ref = ''
|
||||
for _, m in pairs(match_res) do
|
||||
if ref ~= '' then
|
||||
ref = ref .. '; '
|
||||
end
|
||||
|
||||
if m.dir then
|
||||
ref = ref .. m.ref .. ' $' .. m.dir
|
||||
else
|
||||
ref = ref .. m.ref
|
||||
end
|
||||
end
|
||||
|
||||
-- print(result.name, ref)
|
||||
|
||||
result.ref = ref
|
||||
end
|
||||
end
|
||||
|
||||
@@ -421,14 +444,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
|
||||
|
||||
@@ -33,7 +33,6 @@ function setup()
|
||||
'toll_booth',
|
||||
'sally_port',
|
||||
'gate',
|
||||
'lift_gate',
|
||||
'no',
|
||||
'kerb',
|
||||
'block'
|
||||
|
||||
@@ -41,7 +41,7 @@ function Relations.match_to_ref(relations, ref)
|
||||
local result_match = {}
|
||||
local order = {}
|
||||
for i, r in ipairs(references) do
|
||||
result_match[r] = { forward = nil, backward = nil }
|
||||
result_match[r] = false
|
||||
order[i] = r
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@ function Relations.match_to_ref(relations, ref)
|
||||
if direction then
|
||||
local best_score = -1
|
||||
local best_ref = nil
|
||||
|
||||
|
||||
function find_best(scores)
|
||||
if scores then
|
||||
for k ,v in pairs(scores) do
|
||||
@@ -79,21 +79,9 @@ function Relations.match_to_ref(relations, ref)
|
||||
|
||||
find_best(name_scores)
|
||||
find_best(ref_scores)
|
||||
|
||||
|
||||
if best_ref then
|
||||
local result_direction = result_match[best_ref]
|
||||
|
||||
local is_forward = rel["route_forward"]
|
||||
if is_forward == nil then
|
||||
result_direction.forward = direction
|
||||
result_direction.backward = direction
|
||||
elseif is_forward == true then
|
||||
result_direction.forward = direction
|
||||
else
|
||||
result_direction.backward = direction
|
||||
end
|
||||
|
||||
result_match[best_ref] = result_direction
|
||||
result_match[best_ref] = direction
|
||||
end
|
||||
end
|
||||
|
||||
@@ -194,6 +182,7 @@ function Relations.parse_route_relation(rel, way, relations)
|
||||
local super_dir = get_direction_from_superrel(rel, relations)
|
||||
|
||||
-- check if there are data error
|
||||
|
||||
if (result_direction ~= nil) and (super_dir ~= nil) and (result_direction ~= super_dir) then
|
||||
print('ERROR: conflicting relation directions found for way ' .. way:id() ..
|
||||
' relation direction is ' .. result_direction .. ' superrelation direction is ' .. super_dir)
|
||||
@@ -203,59 +192,11 @@ function Relations.parse_route_relation(rel, way, relations)
|
||||
end
|
||||
|
||||
result['route_direction'] = result_direction
|
||||
|
||||
if role == 'forward' then
|
||||
result['route_forward'] = true
|
||||
elseif role == 'backward' then
|
||||
result['route_forward'] = false
|
||||
else
|
||||
result['route_forward'] = nil
|
||||
end
|
||||
|
||||
add_extra_data(m)
|
||||
end
|
||||
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function Relations.process_way_refs(way, relations, result)
|
||||
local parsed_rel_list = {}
|
||||
local rel_id_list = relations:get_relations(way)
|
||||
for i, rel_id in ipairs(rel_id_list) do
|
||||
local rel = relations:relation(rel_id)
|
||||
parsed_rel_list[i] = Relations.parse_route_relation(rel, way, relations)
|
||||
end
|
||||
|
||||
-- now process relations data
|
||||
local matched_refs = nil;
|
||||
if result.ref then
|
||||
local match_res = Relations.match_to_ref(parsed_rel_list, result.ref)
|
||||
|
||||
function gen_ref(is_forward)
|
||||
local ref = ''
|
||||
for _, m in pairs(match_res) do
|
||||
if ref ~= '' then
|
||||
ref = ref .. '; '
|
||||
end
|
||||
|
||||
local dir = m.dir.forward
|
||||
if is_forward == false then
|
||||
dir = m.dir.backward
|
||||
end
|
||||
|
||||
if dir then
|
||||
ref = ref .. m.ref .. ' $' .. dir
|
||||
else
|
||||
ref = ref .. m.ref
|
||||
end
|
||||
end
|
||||
|
||||
return ref
|
||||
end
|
||||
|
||||
result.forward_ref = gen_ref(true)
|
||||
result.backward_ref = gen_ref(false)
|
||||
end
|
||||
end
|
||||
|
||||
return Relations
|
||||
return Relations
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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,12 +365,8 @@ 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;
|
||||
|
||||
const auto ebn_weight = m_edge_based_node_weights[nbe_to_ebn_mapping[eid]];
|
||||
BOOST_ASSERT(ebn_weight == INVALID_EDGE_WEIGHT || ebn_weight == edge_data.weight);
|
||||
m_edge_based_node_weights.push_back(ebn_weight);
|
||||
m_edge_based_node_weights.push_back(m_edge_based_node_weights[eid]);
|
||||
|
||||
edge_based_node_id++;
|
||||
progress.PrintStatus(progress_counter++);
|
||||
@@ -580,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.IsUTurn(),
|
||||
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
|
||||
|
||||
@@ -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 ¤t,
|
||||
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 = [¤t](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
|
||||
|
||||
@@ -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 =
|
||||
@@ -319,74 +318,67 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
road_classification.SetNumberOfLanes(std::max(road_deduced_num_lanes, // len(turn:lanes)
|
||||
road_classification.GetNumberOfLanes()));
|
||||
|
||||
const auto GetNameID = [this, &parsed_way](bool is_forward) -> NameID {
|
||||
const std::string &ref = is_forward ? parsed_way.forward_ref : parsed_way.backward_ref;
|
||||
// Get the unique identifier for the street name, destination, and ref
|
||||
const auto name_iterator = string_map.find(MapKey(parsed_way.name,
|
||||
parsed_way.destinations,
|
||||
ref,
|
||||
parsed_way.pronunciation,
|
||||
parsed_way.exits));
|
||||
// Get the unique identifier for the street name, destination, and ref
|
||||
const auto name_iterator = string_map.find(MapKey(parsed_way.name,
|
||||
parsed_way.destinations,
|
||||
parsed_way.ref,
|
||||
parsed_way.pronunciation,
|
||||
parsed_way.exits));
|
||||
NameID name_id = EMPTY_NAMEID;
|
||||
if (string_map.end() == name_iterator)
|
||||
{
|
||||
// name_offsets has a sentinel element with the total name data size
|
||||
// take the sentinels index as the name id of the new name data pack
|
||||
// (name [name_id], destination [+1], pronunciation [+2], ref [+3], exits [+4])
|
||||
name_id = external_memory.name_offsets.size() - 1;
|
||||
|
||||
NameID name_id = EMPTY_NAMEID;
|
||||
if (string_map.end() == name_iterator)
|
||||
{
|
||||
// name_offsets has a sentinel element with the total name data size
|
||||
// take the sentinels index as the name id of the new name data pack
|
||||
// (name [name_id], destination [+1], pronunciation [+2], ref [+3], exits [+4])
|
||||
name_id = external_memory.name_offsets.size() - 1;
|
||||
std::copy(parsed_way.name.begin(),
|
||||
parsed_way.name.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
std::copy(parsed_way.name.begin(),
|
||||
parsed_way.name.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
std::copy(parsed_way.destinations.begin(),
|
||||
parsed_way.destinations.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
std::copy(parsed_way.destinations.begin(),
|
||||
parsed_way.destinations.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
std::copy(parsed_way.pronunciation.begin(),
|
||||
parsed_way.pronunciation.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
std::copy(parsed_way.pronunciation.begin(),
|
||||
parsed_way.pronunciation.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
std::copy(parsed_way.ref.begin(),
|
||||
parsed_way.ref.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
std::copy(ref.begin(), ref.end(), std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
std::copy(parsed_way.exits.begin(),
|
||||
parsed_way.exits.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
std::copy(parsed_way.exits.begin(),
|
||||
parsed_way.exits.end(),
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
|
||||
|
||||
auto k = MapKey{parsed_way.name,
|
||||
parsed_way.destinations,
|
||||
ref,
|
||||
parsed_way.pronunciation,
|
||||
parsed_way.exits};
|
||||
auto v = MapVal{name_id};
|
||||
string_map.emplace(std::move(k), std::move(v));
|
||||
}
|
||||
else
|
||||
{
|
||||
name_id = name_iterator->second;
|
||||
}
|
||||
|
||||
return name_id;
|
||||
};
|
||||
|
||||
const NameID forward_name_id = GetNameID(true);
|
||||
const NameID backward_name_id = GetNameID(false);
|
||||
auto k = MapKey{parsed_way.name,
|
||||
parsed_way.destinations,
|
||||
parsed_way.ref,
|
||||
parsed_way.pronunciation,
|
||||
parsed_way.exits};
|
||||
auto v = MapVal{name_id};
|
||||
string_map.emplace(std::move(k), std::move(v));
|
||||
}
|
||||
else
|
||||
{
|
||||
name_id = name_iterator->second;
|
||||
}
|
||||
|
||||
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 =
|
||||
@@ -394,13 +386,12 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
|
||||
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
||||
(turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes) ||
|
||||
(parsed_way.forward_ref != parsed_way.backward_ref));
|
||||
(turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes));
|
||||
|
||||
if (in_forward_direction)
|
||||
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
|
||||
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
|
||||
external_memory.all_edges_annotation_data_list.push_back({forward_name_id,
|
||||
external_memory.all_edges_annotation_data_list.push_back({name_id,
|
||||
turn_lane_id_forward,
|
||||
forward_classes,
|
||||
parsed_way.forward_travel_mode,
|
||||
@@ -433,7 +424,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
if (in_backward_direction && (!in_forward_direction || split_edge))
|
||||
{ // add (backward) segments for split edges or not in forward direction
|
||||
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
|
||||
external_memory.all_edges_annotation_data_list.push_back({backward_name_id,
|
||||
external_memory.all_edges_annotation_data_list.push_back({name_id,
|
||||
turn_lane_id_backward,
|
||||
backward_classes,
|
||||
parsed_way.backward_travel_mode,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,10 @@ 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) {
|
||||
return util::guidance::requiresNameAnnounced(road_name_id, //
|
||||
const auto unnamed = road_name_id == EMPTY_NAMEID;
|
||||
|
||||
return unnamed ||
|
||||
util::guidance::requiresNameAnnounced(road_name_id, //
|
||||
candidate_data.name_id, //
|
||||
name_table, //
|
||||
street_name_suffix_table); //
|
||||
@@ -497,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,
|
||||
@@ -577,7 +575,7 @@ 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)
|
||||
{
|
||||
intersection[*obvious].instruction.type = TurnType::NewName;
|
||||
intersection[*obvious].instruction.direction_modifier =
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
@@ -295,16 +369,8 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
||||
&ExtractionWay::backward_rate,
|
||||
"name",
|
||||
sol::property(&ExtractionWay::GetName, &ExtractionWay::SetName),
|
||||
"ref", // backward compatibility
|
||||
sol::property(&ExtractionWay::GetForwardRef,
|
||||
[](ExtractionWay &way, const char *ref) {
|
||||
way.SetForwardRef(ref);
|
||||
way.SetBackwardRef(ref);
|
||||
}),
|
||||
"forward_ref",
|
||||
sol::property(&ExtractionWay::GetForwardRef, &ExtractionWay::SetForwardRef),
|
||||
"backward_ref",
|
||||
sol::property(&ExtractionWay::GetBackwardRef, &ExtractionWay::SetBackwardRef),
|
||||
"ref",
|
||||
sol::property(&ExtractionWay::GetRef, &ExtractionWay::SetRef),
|
||||
"pronunciation",
|
||||
sol::property(&ExtractionWay::GetPronunciation, &ExtractionWay::SetPronunciation),
|
||||
"destinations",
|
||||
@@ -413,6 +479,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 +645,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 +685,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 +843,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 +856,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 +869,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 +884,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 +899,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 +912,6 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
|
||||
|
||||
switch (context.api_version)
|
||||
{
|
||||
case 4:
|
||||
case 3:
|
||||
case 2:
|
||||
if (context.has_turn_penalty_function)
|
||||
@@ -1005,14 +943,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 +979,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 +1003,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 +1024,6 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way,
|
||||
|
||||
switch (api_version)
|
||||
{
|
||||
case 4:
|
||||
case 3:
|
||||
way_function(profile_table, way, result, relations);
|
||||
break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user