From aadc0880846e059272b66f6bad920a0a35bedd51 Mon Sep 17 00:00:00 2001 From: Siarhei Fedartsou Date: Fri, 19 Aug 2022 23:31:40 +0200 Subject: [PATCH 01/12] Fix distance calculation consistency. (#6315) Consolidate great circle distance calculations to use cheap ruler library. --- .github/workflows/osrm-backend.yml | 4 +- CHANGELOG.md | 1 + CMakeLists.txt | 2 +- features/bicycle/exclude.feature | 2 +- features/bicycle/maxspeed.feature | 14 +- features/bicycle/safety.feature | 14 +- features/bicycle/surface.feature | 18 +- features/bicycle/turn_penalty.feature | 4 +- features/car/access.feature | 6 +- features/car/ferry.feature | 10 +- features/car/maxspeed.feature | 68 ++--- features/car/speed.feature | 38 +-- features/car/startpoint.feature | 8 +- features/car/surface.feature | 2 +- features/car/traffic_light_penalties.feature | 6 +- features/car/weight.feature | 2 +- features/guidance/anticipate-lanes.feature | 30 +- .../guidance/dedicated-turn-roads.feature | 2 +- .../guidance/merge-segregated-roads.feature | 4 +- .../guidance/obvious-turn-discovery.feature | 2 +- features/guidance/ramp.feature | 8 +- features/guidance/roundabout.feature | 10 +- features/guidance/turn-lanes.feature | 6 +- features/raster/extract.feature | 4 +- features/step_definitions/routability.js | 13 +- features/support/data.js | 19 +- features/testbot/annotations.feature | 2 +- features/testbot/bearing_param.feature | 18 +- features/testbot/compression.feature | 4 +- features/testbot/distance.feature | 12 +- features/testbot/distance_matrix.feature | 272 +++++++++--------- features/testbot/duration_matrix.feature | 114 ++++---- features/testbot/matching.feature | 40 +-- features/testbot/multi_level_routing.feature | 29 +- features/testbot/origin.feature | 4 +- features/testbot/planetary.feature | 14 +- features/testbot/projection.feature | 14 +- features/testbot/traffic_speeds.feature | 58 ++-- .../testbot/traffic_turn_penalties.feature | 6 +- features/testbot/trip.feature | 2 +- features/testbot/weight.feature | 56 ++-- include/engine/api/base_api.hpp | 10 +- include/engine/api/match_parameters_tidy.hpp | 2 +- include/engine/geospatial_query.hpp | 12 +- include/engine/guidance/assemble_geometry.hpp | 4 +- include/engine/plugins/plugin_base.hpp | 4 +- .../routing_algorithms/routing_base.hpp | 2 +- .../intersection/node_based_graph_walker.hpp | 2 +- include/util/coordinate_calculation.hpp | 5 - package-lock.json | 26 +- package.json | 1 + src/engine/guidance/assemble_steps.cpp | 6 +- src/engine/guidance/post_processing.cpp | 8 +- src/engine/plugins/table.cpp | 4 +- src/engine/plugins/tile.cpp | 2 +- .../alternative_path_mld.cpp | 2 +- .../routing_algorithms/map_matching.cpp | 4 +- src/extractor/extraction_containers.cpp | 2 +- .../intersection/coordinate_extractor.cpp | 36 +-- .../intersection/intersection_analysis.cpp | 2 +- .../intersection/mergable_road_detector.cpp | 11 +- .../intersection/node_based_graph_walker.cpp | 2 +- src/guidance/intersection_handler.cpp | 2 +- src/guidance/roundabout_handler.cpp | 2 +- ...segregated_intersection_classification.cpp | 2 +- src/guidance/sliproad_handler.cpp | 8 +- src/guidance/turn_discovery.cpp | 2 +- src/util/coordinate_calculation.cpp | 100 ++----- test/nodejs/constants.js | 2 +- test/nodejs/route.js | 2 +- .../.clang-format | 0 .../.gitignore | 0 .../.travis.yml | 0 .../CMakeLists.txt | 0 .../LICENSE | 0 .../README.md | 0 .../cmake/build.cmake | 0 .../cmake/mason.cmake | 0 .../include/mapbox/cheap_ruler.hpp | 156 ++++++---- .../test/cheap_ruler.cpp | 88 +++++- .../test/fixtures/lines.hpp | 0 .../test/fixtures/turf.hpp | 0 unit_tests/library/tile.cpp | 8 +- unit_tests/util/coordinate_calculation.cpp | 2 +- 84 files changed, 780 insertions(+), 683 deletions(-) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/.clang-format (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/.gitignore (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/.travis.yml (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/CMakeLists.txt (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/LICENSE (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/README.md (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/cmake/build.cmake (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/cmake/mason.cmake (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/include/mapbox/cheap_ruler.hpp (67%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/test/cheap_ruler.cpp (65%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/test/fixtures/lines.hpp (100%) rename third_party/{cheap-ruler-cpp-2.5.4 => cheap-ruler-cpp-2778eb8}/test/fixtures/turf.hpp (100%) diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index 9ab578065..ae4c1073e 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -472,9 +472,9 @@ jobs: uses: actions/cache@v2 with: path: ${{github.workspace}}/test/cache - key: test-${{ matrix.name }}-${{ github.sha }} + key: v2-test-${{ matrix.name }}-${{ github.sha }} restore-keys: | - test-${{ matrix.name }}- + v2-test-${{ matrix.name }}- - name: Prepare environment run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a639194e..f4d1f62a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - Misc: + - FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315) - FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304) - CHANGED: Pass osm_node_ids by reference in osrm::updater::Updater class. [#6298](https://github.com/Project-OSRM/osrm-backend/pull/6298) - FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bf19bbac..41875bbef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -425,7 +425,7 @@ include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR}) set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-0.9.2/include") include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR}) -set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include") +set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2778eb8/include") include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR}) add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c") diff --git a/features/bicycle/exclude.feature b/features/bicycle/exclude.feature index 6fdcbfb07..f88315408 100644 --- a/features/bicycle/exclude.feature +++ b/features/bicycle/exclude.feature @@ -45,7 +45,7 @@ Feature: Bicycle - Exclude flags When I match I should get | trace | matchings | duration | - | abcf | abcf | 301.2 | + | abcf | abcf | 301 | When I request a travel time matrix I should get | | a | f | diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index a4fc57b3d..72f6a0ed6 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -9,7 +9,7 @@ Feature: Bike - Max speed restrictions Then routability should be | highway | maxspeed | bothw | | residential | | 15 km/h | - | residential | 10 | 9 km/h | + | residential | 10 | 10 km/h | Scenario: Bicycle - Ignore maxspeed when higher than way speed Then routability should be @@ -65,12 +65,12 @@ Feature: Bike - Max speed restrictions Then routability should be | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | | | | | 15 km/h | 15 km/h | - | 10 | | | 9 km/h | 9 km/h | - | | 10 | | 9 km/h | 15 km/h | - | | | 10 | 14 km/h | 9 km/h | - | 2 | 10 | | 9 km/h | 2 km/h | - | 2 | | 10 | 2 km/h | 9 km/h | - | 2 | 5 | 10 | 5 km/h | 9 km/h | + | 10 | | | 10 km/h | 10 km/h | + | | 10 | | 10 km/h | 15 km/h | + | | | 10 | 15 km/h | 10 km/h | + | 2 | 10 | | 10 km/h | 2 km/h | + | 2 | | 10 | 2 km/h | 10 km/h | + | 2 | 5 | 10 | 5 km/h | 10 km/h | Scenario: Bike - Maxspeed should not allow routing on unroutable ways Then routability should be diff --git a/features/bicycle/safety.feature b/features/bicycle/safety.feature index e45dae500..4561e1a5e 100644 --- a/features/bicycle/safety.feature +++ b/features/bicycle/safety.feature @@ -33,7 +33,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | track | 15 km/h | 15 km/h | 4.2 | 4.2 | | residential | track | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | track | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | track | 15 km/h | 15 km/h | 4.2 | 4.2 | + | footway | track | 14 km/h | 14 km/h | 4.2 | 4.2 | | motorway | lane | 15 km/h | | 4.2 | | | primary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | secondary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | @@ -41,7 +41,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | primary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | secondary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | tertiary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | - | residential | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | + | residential | lane | 14 km/h | 14 km/h | 4.2 | 4.2 | | cycleway | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | footway | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | | motorway | shared_lane | 15 km/h | | 4.2 | | @@ -59,7 +59,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 | | residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 | | cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 | - | footway | track | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 | + | footway | track | | 14 km/h | 4 km/h +-1 | 4.2 | 1.1 | | motorway | | track | 15 km/h | | 4.2 | | | primary | | track | 15 km/h | 15 km/h | 2.1 | 4.2 | | secondary | | track | 15 km/h | 15 km/h | 2.7 | 4.2 | @@ -67,7 +67,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | primary_link | | track | 15 km/h | 15 km/h | 2.1 | 4.2 | | secondary_link | | track | 15 km/h | 15 km/h | 2.7 | 4.2 | | tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 | - | residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 | + | residential | | track | 14 km/h | 14 km/h | 4.2 | 4.2 | | cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 | | footway | | track | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 | | motorway | lane | | 15 km/h | | 4.2 | | @@ -75,7 +75,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | secondary | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 | | tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 | | primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 | - | secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 | + | secondary_link | lane | | 14 km/h | 14 km/h | 4.2 | 2.7 | | tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 | | residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 | | cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 | @@ -84,7 +84,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | primary | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 | | secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 2.7 | 4.2 | | tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 | - | primary_link | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 | + | primary_link | | lane | 14 km/h | 14 km/h | 2.1 | 4.2 | | secondary_link | | lane | 15 km/h | 15 km/h | 2.7 | 4.2 | | tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 | | residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 | @@ -92,7 +92,7 @@ Feature: Bicycle - Adds penalties to unsafe roads | footway | | lane | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 | | motorway | shared_lane | | 15 km/h | | 4.2 | | | primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.1 | - | motorway | | shared_lane | 15 km/h | | 4.2 | | + | motorway | | shared_lane | 14 km/h | | 4.2 | | | primary | | shared_lane | 15 km/h | 15 km/h | 2.1 | 4.2 | diff --git a/features/bicycle/surface.feature b/features/bicycle/surface.feature index 1a4b5763a..98ec1c250 100644 --- a/features/bicycle/surface.feature +++ b/features/bicycle/surface.feature @@ -8,29 +8,29 @@ Feature: Bike - Surfaces Then routability should be | highway | surface | bothw | | cycleway | | 48 s | - | cycleway | asphalt | 48 s | + | cycleway | asphalt | 47.9 s | | cycleway | cobblestone:flattened | 72 s | | cycleway | paving_stones | 72 s | | cycleway | compacted | 72 s | | cycleway | cobblestone | 120 s | | cycleway | fine_gravel | 120 s | | cycleway | gravel | 120 s | - | cycleway | pebblestone | 120.1 s | + | cycleway | pebblestone | 120 s | | cycleway | dirt | 120 s | | cycleway | earth | 120 s | | cycleway | grass | 120 s | | cycleway | mud | 240 s | - | cycleway | sand | 240.1 s | + | cycleway | sand | 240 s | | cycleway | sett | 72 s | Scenario: Bicycle - Good surfaces on small paths Then routability should be - | highway | surface | bothw | - | cycleway | | 48 s | - | path | | 60 s | - | track | | 60 s | - | track | asphalt | 60 s | - | path | asphalt | 60 s | + | highway | surface | bothw | + | cycleway | | 48 s | + | path | | 59.9 s | + | track | | 60 s | + | track | asphalt | 60 s | + | path | asphalt | 60 s | Scenario: Bicycle - Surfaces should not make unknown ways routable Then routability should be diff --git a/features/bicycle/turn_penalty.feature b/features/bicycle/turn_penalty.feature index d0c144e32..763827527 100644 --- a/features/bicycle/turn_penalty.feature +++ b/features/bicycle/turn_penalty.feature @@ -37,6 +37,6 @@ Feature: Turn Penalties | from | to | distance | weight | # | | a | c | 900m +- 1 | 216 | Going straight has no penalties | | a | d | 900m +- 1 | 220.2 | Turning right had penalties | - | e | g | 2100m +- 4| 503.9 | Going straght has no penalties | - | e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties| + | e | g | 2100m +- 5| 503.9 | Going straght has no penalties | + | e | h | 2100m +- 5| 515.1 | Turn sharp right has even higher penalties| diff --git a/features/car/access.feature b/features/car/access.feature index 47ac4e3c2..0bebd2589 100644 --- a/features/car/access.feature +++ b/features/car/access.feature @@ -185,7 +185,7 @@ Feature: Car - Restricted access Then routability should be | highway | hov | bothw | forw_rate | backw_rate | | primary | designated | x | 18.2 | 18.2 | - | primary | yes | x | 18.2 | 18.2 | + | primary | yes | x | 18.3 | 18.3 | | primary | no | x | 18.2 | 18.2 | # Models: @@ -196,7 +196,7 @@ Feature: Car - Restricted access Then routability should be | highway | hov | hov:lanes | lanes | access | oneway | forw | backw | forw_rate | | motorway | designated | designated\|designated\|designated | 3 | hov | yes | x | | 25 | - | motorway | lane | | 3 | designated | yes | x | | 25 | + | motorway | lane | | 3 | designated | yes | x | | 25.3 | @hov Scenario: Car - a way with all lanes HOV-designated is highly penalized by default (similar to hov=designated) @@ -206,7 +206,7 @@ Feature: Car - Restricted access # This test is flaky because non-deterministic turn generation sometimes emits a NoTurn here that is marked as restricted. #3769 #| primary | | designated | | | x | x | 18.2 | 18.2 | #| primary | designated | | | | x | x | 18.2 | 18.2 | - | primary | designated\|designated | designated\|designated | | | x | x | 18.2 | 18.2 | + | primary | designated\|designated | designated\|designated | | | x | x | 18.3 | 18.3 | | primary | designated\|no | designated\|no | | | x | x | 18.2 | 18.2 | | primary | yes\|no | yes\|no | | | x | x | 18.2 | 18.2 | | primary | | | | | x | x | 18.2 | 18.2 | diff --git a/features/car/ferry.feature b/features/car/ferry.feature index 5a8de7b1b..e5b7d363c 100644 --- a/features/car/ferry.feature +++ b/features/car/ferry.feature @@ -46,10 +46,10 @@ Feature: Car - Handle ferry routes When I route I should get | from | to | route | modes | speed | time | - | a | g | abc,cde,efg,efg | driving,ferry,driving,driving | 12 km/h | 173.4s | - | b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 9 km/h | 162.4s | - | c | e | cde,cde | ferry,ferry | 5 km/h | 151.4s | - | e | c | cde,cde | ferry,ferry | 5 km/h | 151.4s | + | a | g | abc,cde,efg,efg | driving,ferry,driving,driving | 12 km/h | 173.5s | + | b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 9 km/h | 162.5s | + | c | e | cde,cde | ferry,ferry | 5 km/h | 151.5s | + | e | c | cde,cde | ferry,ferry | 5 km/h | 151.5s | Scenario: Car - Properly handle simple durations Given the node map @@ -117,4 +117,4 @@ Feature: Car - Handle ferry routes # Note that matching *should* work across unsnappable ferries When I match I should get | trace | geometry | duration | - | abcdef| 1,1,1.000899,1,1.000899,1,1.002697,1,1.002697,1,1.003596,1,1.003596,1,1.005394,1,1.005394,1,1.006293,1 | 610.9 | + | abcdef| 1,1,1.000898,1,1.000898,1,1.002695,1,1.002695,1,1.003594,1,1.003594,1,1.005391,1,1.005391,1,1.006289,1 | 611 | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index c7169b37c..d2b8b4f5f 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -86,57 +86,57 @@ OSRM will use 4/5 of the projected free-flow speed. Then routability should be | highway | maxspeed | width | maxspeed:forward | maxspeed:backward | forw | backw | forw_rate | backw_rate | - | primary | | | | | 64 km/h | 64 km/h | 18 | 18 | + | primary | | | | | 64 km/h | 64 km/h | 18.1 | 18.1 | | primary | | 3 | | | 64 km/h | 64 km/h | 9 | 9 | - | primary | 60 | | | | 47 km/h | 47 km/h | 13.3 | 13.3 | - | primary | 60 | 3 | | | 47 km/h | 47 km/h | 6.7 | 6.7 | - | primary | | | 60 | | 47 km/h | 64 km/h | 13.3 | 18 | - | primary | | 3 | 60 | | 47 km/h | 64 km/h | 6.7 | 9 | - | primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13.3 | - | primary | | 3 | | 60 | 64 km/h | 47 km/h | 9 | 6.7 | - | primary | 15 | | 60 | | 47 km/h | 11 km/h | 13.3 | 3.3 | + | primary | 60 | | | | 48 km/h | 48 km/h | 13.3 | 13.3 | + | primary | 60 | 3 | | | 48 km/h | 48 km/h | 6.7 | 6.7 | + | primary | | | 60 | | 48 km/h | 64 km/h | 13.3 | 18.1 | + | primary | | 3 | 60 | | 48 km/h | 64 km/h | 6.7 | 9 | + | primary | | | | 60 | 64 km/h | 48 km/h | 18.1 | 13.3 | + | primary | | 3 | | 60 | 64 km/h | 48 km/h | 9 | 6.7 | + | primary | 15 | | 60 | | 48 km/h | 12 km/h | 13.3 | 3.3 | | primary | 15 | 3 | 60 | | 48 km/h | 12 km/h | 6.7 | 1.7 | - | primary | 15 | | | 60 | 12 km/h | 47 km/h | 3.3 | 13.3 | - | primary | 15 | 3 | | 60 | 12 km/h | 47 km/h | 1.7 | 6.7 | - | primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 6.7 | 13.3 | - | primary | 15 | 3 | 30 | 60 | 23 km/h | 47 km/h | 3.3 | 6.7 | + | primary | 15 | | | 60 | 12 km/h | 48 km/h | 3.3 | 13.3 | + | primary | 15 | 3 | | 60 | 12 km/h | 48 km/h | 1.7 | 6.7 | + | primary | 15 | | 30 | 60 | 24 km/h | 48 km/h | 6.7 | 13.3 | + | primary | 15 | 3 | 30 | 60 | 24 km/h | 48 km/h | 3.3 | 6.7 | Scenario: Car - Single lane streets be ignored or incur a penalty Then routability should be | highway | maxspeed | lanes | maxspeed:forward | maxspeed:backward | forw | backw | forw_rate | backw_rate | - | primary | | | | | 64 km/h | 64 km/h | 18 | 18 | + | primary | | | | | 64 km/h | 64 km/h | 18.1 | 18.1 | | primary | | 1 | | | 64 km/h | 64 km/h | 9 | 9 | - | primary | 60 | | | | 47 km/h | 47 km/h | 13.3 | 13.3 | - | primary | 60 | 1 | | | 47 km/h | 47 km/h | 6.7 | 6.7 | - | primary | | | 60 | | 47 km/h | 64 km/h | 13.3 | 18 | - | primary | | 1 | 60 | | 47 km/h | 64 km/h | 6.7 | 9 | - | primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13.3 | - | primary | | 1 | | 60 | 64 km/h | 47 km/h | 9 | 6.7 | - | primary | 15 | | 60 | | 47 km/h | 11 km/h | 13.3 | 3.3 | + | primary | 60 | | | | 48 km/h | 48 km/h | 13.3 | 13.3 | + | primary | 60 | 1 | | | 48 km/h | 48 km/h | 6.7 | 6.7 | + | primary | | | 60 | | 48 km/h | 64 km/h | 13.3 | 18.1 | + | primary | | 1 | 60 | | 48 km/h | 64 km/h | 6.7 | 9 | + | primary | | | | 60 | 64 km/h | 48 km/h | 18.1 | 13.3 | + | primary | | 1 | | 60 | 64 km/h | 48 km/h | 9 | 6.7 | + | primary | 15 | | 60 | | 48 km/h | 12 km/h | 13.3 | 3.3 | | primary | 15 | 1 | 60 | | 48 km/h | 12 km/h | 6.7 | 1.7 | - | primary | 15 | | | 60 | 12 km/h | 47 km/h | 3.3 | 13.3 | - | primary | 15 | 1 | | 60 | 12 km/h | 47 km/h | 1.7 | 6.7 | - | primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 6.7 | 13.3 | - | primary | 15 | 1 | 30 | 60 | 23 km/h | 47 km/h | 3.3 | 6.7 | + | primary | 15 | | | 60 | 12 km/h | 48 km/h | 3.3 | 13.3 | + | primary | 15 | 1 | | 60 | 12 km/h | 48 km/h | 1.7 | 6.7 | + | primary | 15 | | 30 | 60 | 24 km/h | 48 km/h | 6.7 | 13.3 | + | primary | 15 | 1 | 30 | 60 | 24 km/h | 48 km/h | 3.3 | 6.7 | Scenario: Car - Single lane streets only incur a penalty for two-way streets Then routability should be | highway | maxspeed | lanes | oneway | forw | backw | forw_rate | backw_rate | - | primary | 30 | 1 | yes | 23 km/h | | 6.7 | | - | primary | 30 | 1 | -1 | | 23 km/h | | 6.7 | - | primary | 30 | 1 | | 23 km/h | 23 km/h | 3.3 | 3.3 | - | primary | 30 | 2 | | 23 km/h | 23 km/h | 6.7 | 6.7 | + | primary | 30 | 1 | yes | 24 km/h | | 6.7 | | + | primary | 30 | 1 | -1 | | 24 km/h | | 6.7 | + | primary | 30 | 1 | | 24 km/h | 24 km/h | 3.3 | 3.3 | + | primary | 30 | 2 | | 24 km/h | 24 km/h | 6.7 | 6.7 | Scenario: Car - Forward/backward maxspeed on reverse oneways Then routability should be | highway | maxspeed | maxspeed:forward | maxspeed:backward | oneway | forw | backw | forw_rate | backw_rate | - | primary | | | | -1 | | 64 km/h | | 18 | - | primary | 30 | | | -1 | | 23 km/h | | 6.7 | - | primary | | 30 | | -1 | | 64 km/h | | 18 | - | primary | | | 30 | -1 | | 23 km/h | | 6.7 | - | primary | 20 | 30 | | -1 | | 15 km/h | | 4.4 | - | primary | 20 | | 30 | -1 | | 23 km/h | | 6.7 | + | primary | | | | -1 | | 64 km/h | | 18.1 | + | primary | 30 | | | -1 | | 24 km/h | | 6.7 | + | primary | | 30 | | -1 | | 64 km/h | | 18.1 | + | primary | | | 30 | -1 | | 24 km/h | | 6.7 | + | primary | 20 | 30 | | -1 | | 16 km/h | | 4.4 | + | primary | 20 | | 30 | -1 | | 24 km/h | | 6.7 | Scenario: Car - Respect source:maxspeed diff --git a/features/car/speed.feature b/features/car/speed.feature index bbbb67b6f..37d9f3512 100644 --- a/features/car/speed.feature +++ b/features/car/speed.feature @@ -9,29 +9,29 @@ Feature: Car - speeds Scenario: Car - speed of various way types Then routability should be | highway | oneway | bothw | - | motorway | no | 89 km/h | - | motorway_link | no | 44 km/h | - | trunk | no | 85 km/h | - | trunk_link | no | 39 km/h | + | motorway | no | 90 km/h | + | motorway_link | no | 45 km/h | + | trunk | no | 84 km/h | + | trunk_link | no | 40 km/h | | primary | no | 64 km/h | - | primary_link | no | 29 km/h | - | secondary | no | 55 km/h | - | secondary_link | no | 24 km/h | - | tertiary | no | 39 km/h | + | primary_link | no | 30 km/h | + | secondary | no | 54 km/h | + | secondary_link | no | 25 km/h | + | tertiary | no | 40 km/h | | tertiary_link | no | 20 km/h | - | unclassified | no | 24 km/h | - | residential | no | 24 km/h | - | living_street | no | 9 km/h | + | unclassified | no | 25 km/h | + | residential | no | 25 km/h | + | living_street | no | 10 km/h | | service | no | 15 km/h | # Alternating oneways scale rates but not speeds Scenario: Car - scaled speeds for oneway=alternating Then routability should be | highway | oneway | junction | forw | backw | # | - | tertiary | | | 39 km/h | 39 km/h | | - | tertiary | alternating | | 39 km/h | 39 km/h | | - | motorway | | | 89 km/h | | implied oneway | - | motorway | alternating | | 89 km/h | | implied oneway | + | tertiary | | | 40 km/h | 40 km/h | | + | tertiary | alternating | | 40 km/h | 40 km/h | | + | motorway | | | 90 km/h | | implied oneway | + | motorway | alternating | | 90 km/h | | implied oneway | | motorway | reversible | | | | unroutable | | primary | | roundabout | 64 km/h | | implied oneway | | primary | alternating | roundabout | 64 km/h | | implied oneway | @@ -42,12 +42,12 @@ Feature: Car - speeds | highway | maxspeed | forw | backw | | primary | | 64 km/h | 64 km/h | - | primary | 60 | 47 km/h | 47 km/h | - | primary | 60 | 47 km/h | 47 km/h | - | primary | 60 | 47 km/h | 47 km/h | + | primary | 60 | 48 km/h | 48 km/h | + | primary | 60 | 48 km/h | 48 km/h | + | primary | 60 | 48 km/h | 48 km/h | Scenario: Car - Side road penalties Then routability should be | highway | side_road | forw | backw | forw_rate | backw_rate | - | primary | yes | 64 km/h | 64 km/h | 14.4 | 14.4 | + | primary | yes | 64 km/h | 64 km/h | 14.5 | 14.5 | diff --git a/features/car/startpoint.feature b/features/car/startpoint.feature index 9e753843b..696f1ae31 100644 --- a/features/car/startpoint.feature +++ b/features/car/startpoint.feature @@ -53,8 +53,8 @@ Feature: Car - Allowed start/end modes When I request a travel time matrix I should get | | 2 | c | - | 1 | 59.1 | 35.1 | - | b | 35.1 | 11.1 | + | 1 | 59.1 | 35.2 | + | b | 35 | 11.1 | When I route I should get | from | to | route | @@ -121,5 +121,5 @@ Feature: Car - Allowed start/end modes When I request a travel time matrix I should get | | 2 | c | - | 1 | 59.1 | 35.1 | - | b | 35.1 | 11.1 | \ No newline at end of file + | 1 | 59.1 | 35.2 | + | b | 35 | 11.1 | \ No newline at end of file diff --git a/features/car/surface.feature b/features/car/surface.feature index 8984a8e06..067e56500 100644 --- a/features/car/surface.feature +++ b/features/car/surface.feature @@ -65,7 +65,7 @@ Feature: Car - Surfaces Then routability should be | highway | oneway | surface | forw | backw | | motorway | no | | 90 km/h | 90 km/h | - | motorway | no | asphalt | 90 km/h | 90 km/h +-1 | + | motorway | no | asphalt | 91 km/h | 90 km/h +-1 | | motorway | no | concrete | 90 km/h +-1 | 90 km/h +-1 | | motorway | no | concrete:plates | 90 km/h +-1 | 90 km/h +-1 | | motorway | no | concrete:lanes | 90 km/h +-1 | 90 km/h +-1 | diff --git a/features/car/traffic_light_penalties.feature b/features/car/traffic_light_penalties.feature index e5bc313a0..e8961abb1 100644 --- a/features/car/traffic_light_penalties.feature +++ b/features/car/traffic_light_penalties.feature @@ -59,7 +59,7 @@ Feature: Car - Handle traffic lights When I route I should get | from | to | route | geometry | - | a | c | abc,abc | _ibE_ibE?gJ?gJ | + | a | c | abc,abc | _ibE_ibE?gJ?eJ | @traffic Scenario: Traffic update on the edge with a traffic signal @@ -89,5 +89,5 @@ Feature: Car - Handle traffic lights When I route I should get | from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight | - | a | c | abc,abc | 59 km/h | 24.2,0 | 24.2s | 399.9m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 | - | c | a | abc,abc | 59 km/h | 24.2,0 | 24.2s | 399.9m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 | + | a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 | + | c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 | diff --git a/features/car/weight.feature b/features/car/weight.feature index 6bf7a1d6e..d7f02ac57 100644 --- a/features/car/weight.feature +++ b/features/car/weight.feature @@ -83,4 +83,4 @@ Feature: Car - weights | waypoints | bearings | route | distance | weights | times | | a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s | | b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s | - | a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s | + | a,d | 90 180 | abc,bd,bd | 400m | 200,200,0 | 13.2s,11.1s,0s | diff --git a/features/guidance/anticipate-lanes.feature b/features/guidance/anticipate-lanes.feature index c082dc3c1..74f6f7d4c 100644 --- a/features/guidance/anticipate-lanes.feature +++ b/features/guidance/anticipate-lanes.feature @@ -103,7 +103,7 @@ Feature: Turn Lane Guidance When I route I should get | waypoints | route | turns | lanes | - | a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight left:false slight left:true,straight:false slight right:true, | + | a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight left:true slight left:true,straight:false slight right:true, | @anticipate @@ -364,8 +364,8 @@ Feature: Turn Lane Guidance When I route I should get | waypoints | route | turns | lanes | - | a,d | main,left,left | depart,end of road left,arrive | ;left:false straight:false straight:true straight:false straight:false right:false;left:false straight:true straight:false right:false,left:true right:false, | - | a,e | main,right,right | depart,end of road right,arrive | ;left:false straight:false straight:false straight:true straight:false right:false;left:false straight:false straight:true right:false,left:false right:true, | + | a,d | main,left,left | depart,end of road left,arrive | ;left:false straight:true straight:true straight:true straight:true right:false;left:false straight:true straight:true right:false,left:true right:false, | + | a,e | main,right,right | depart,end of road right,arrive | ;left:false straight:true straight:true straight:true straight:true right:false;left:false straight:true straight:true right:false,left:false right:true, | @anticipate Scenario: Anticipate Lanes for through with turn before / after @@ -390,15 +390,15 @@ Feature: Turn Lane Guidance | il | | il | | When I route I should get - | waypoints | route | turns | lanes | # | - | a,f | ab,bdehi,ef,ef | depart,turn right,turn right,arrive | ,right:false right:false right:true right:true,left:false left:false straight:false straight:false straight:false straight:false right:true right:true, | | - | a,g | ab,bdehi,eg,eg | depart,turn right,turn left,arrive | ,right:true right:true right:false right:false,left:true left:true straight:false straight:false straight:false straight:false right:false right:false, | | - | a,j | ab,bdehi,ij,ij | depart,turn right,end of road right,arrive | ,right:true right:true right:false right:false;left:false left:false straight:false straight:false straight:true straight:true right:false right:false,left:false left:false right:true right:true, | | - | a,l | ab,bdehi,il,il | depart,turn right,end of road left,arrive | ,right:false right:false right:true right:true;left:false left:false straight:true straight:true straight:false straight:false right:false right:false,left:true left:true right:false right:false, | not perfect | - | c,g | cb,bdehi,eg,eg | depart,turn left,turn left,arrive | ,left:true left:true left:false left:false,left:true left:true straight:false straight:false straight:false straight:false right:false right:false, | | - | c,f | cb,bdehi,ef,ef | depart,turn left,turn right,arrive | ,left:false left:false left:true left:true,left:false left:false straight:false straight:false straight:false straight:false right:true right:true, | | - | c,l | cb,bdehi,il,il | depart,turn left,end of road left,arrive | ,left:false left:false left:true left:true;left:false left:false straight:true straight:true straight:false straight:false right:false right:false,left:true left:true right:false right:false, | | - | c,j | cb,bdehi,ij,ij | depart,turn left,end of road right,arrive | ,left:true left:true left:false left:false;left:false left:false straight:false straight:false straight:true straight:true right:false right:false,left:false left:false right:true right:true, | not perfect | + | waypoints | route | turns | lanes | # | + | a,f | ab,bdehi,ef,ef | depart,turn right,turn right,arrive | ,right:true right:true right:true right:true,left:false left:false straight:false straight:false straight:false straight:false right:true right:true, | | + | a,g | ab,bdehi,eg,eg | depart,turn right,turn left,arrive | ,right:true right:true right:true right:true,left:true left:true straight:false straight:false straight:false straight:false right:false right:false, | | + | a,j | ab,bdehi,ij,ij | depart,turn right,end of road right,arrive | ,right:true right:true right:true right:true;left:false left:false straight:false straight:false straight:true straight:true right:false right:false,left:false left:false right:true right:true, | | + | a,l | ab,bdehi,il,il | depart,turn right,end of road left,arrive | ,right:true right:true right:true right:true;left:false left:false straight:true straight:true straight:false straight:false right:false right:false,left:true left:true right:false right:false, | not perfect | + | c,g | cb,bdehi,eg,eg | depart,turn left,turn left,arrive | ,left:true left:true left:true left:true,left:true left:true straight:false straight:false straight:false straight:false right:false right:false, | | + | c,f | cb,bdehi,ef,ef | depart,turn left,turn right,arrive | ,left:true left:true left:true left:true,left:false left:false straight:false straight:false straight:false straight:false right:true right:true, | | + | c,l | cb,bdehi,il,il | depart,turn left,end of road left,arrive | ,left:true left:true left:true left:true;left:false left:false straight:true straight:true straight:false straight:false right:false right:false,left:true left:true right:false right:false, | | + | c,j | cb,bdehi,ij,ij | depart,turn left,end of road right,arrive | ,left:true left:true left:true left:true;left:false left:false straight:false straight:false straight:true straight:true right:false right:false,left:false left:false right:true right:true, | not perfect | @anticipate Scenario: Anticipate Lanes for turns with through before and after @@ -811,9 +811,9 @@ Feature: Turn Lane Guidance | hj | 7th | | no | When I route I should get - | waypoints | route | turns | locations | lanes | - | a,i | road,road | depart,arrive | a,i | ;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:false;none:true none:true right:false, | - | a,j | road,7th,7th | depart,turn right,arrive | a,h,j | ;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:false none:false none:true;left:false none:false none:false none:true,none:false none:false right:true, | + | waypoints | route | turns | locations | lanes | + | a,i | road,road | depart,arrive | a,i | ;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;none:true none:true right:false, | + | a,j | road,7th,7th | depart,turn right,arrive | a,h,j | ;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:true none:true none:true;left:false none:false none:false none:true,none:false none:false right:true, | @anticipate Scenario: Oak St, Franklin St diff --git a/features/guidance/dedicated-turn-roads.feature b/features/guidance/dedicated-turn-roads.feature index 03213bd70..055f2af88 100644 --- a/features/guidance/dedicated-turn-roads.feature +++ b/features/guidance/dedicated-turn-roads.feature @@ -687,7 +687,7 @@ Feature: Slipways and Dedicated Turn Lanes When I route I should get | waypoints | route | turns | locations | - | s,f | sabc,ae,dbef,dbef | depart,fork slight right,turn right,arrive | s,a,e,f | + | s,f | sabc,ae,dbef,dbef | depart,turn straight,turn right,arrive | s,a,e,f | @sliproads Scenario: Traffic Signal on Sliproad diff --git a/features/guidance/merge-segregated-roads.feature b/features/guidance/merge-segregated-roads.feature index 8134a2fc0..c802d4ade 100644 --- a/features/guidance/merge-segregated-roads.feature +++ b/features/guidance/merge-segregated-roads.feature @@ -64,7 +64,7 @@ Feature: Merge Segregated Roads When I route I should get | waypoints | route | intersections | - | a,f | road,road,road,road | true:90,false:45 true:135 false:270;true:45 true:180 false:315;true:90 false:225 true:315;true:270 | + | a,f | road,road,road | true:90,false:45 true:135 false:270;true:45 true:180 false:315,true:90 false:225 true:315;true:270 | #https://www.openstreetmap.org/#map=19/52.50003/13.33915 @negative @@ -193,7 +193,7 @@ Feature: Merge Segregated Roads When I route I should get | waypoints | route | intersections | - | a,g | road,road | true:90,false:90 true:150 false:270,true:90 false:270 true:345;true:270 | + | a,g | road,road | true:90,false:90 true:165 false:270,true:90 false:270 true:345;true:270 | Scenario: Merging parallel roads with intermediate bridges # https://www.mapillary.com/app/?lat=52.466483333333336&lng=13.431908333333332&z=17&focus=photo&pKey=LWXnKqoGqUNLnG0lofiO0Q diff --git a/features/guidance/obvious-turn-discovery.feature b/features/guidance/obvious-turn-discovery.feature index fd846acef..0ad8a0845 100644 --- a/features/guidance/obvious-turn-discovery.feature +++ b/features/guidance/obvious-turn-discovery.feature @@ -277,7 +277,7 @@ Feature: Simple Turns When I route I should get | from | to | route | turns | | a | c | menz,rem | depart,arrive | - | d | c | rem,rem,rem | depart,continue left,arrive | + | d | c | rem,rem | depart,arrive | | c | d | rem,rem,rem | depart,continue right,arrive | | c | a | rem,menz | depart,arrive | diff --git a/features/guidance/ramp.feature b/features/guidance/ramp.feature index a4e823ded..560952d0b 100644 --- a/features/guidance/ramp.feature +++ b/features/guidance/ramp.feature @@ -160,8 +160,8 @@ Feature: Ramp Guidance When I route I should get | waypoints | route | turns | - | a,d | ab,bd,bd | depart,on ramp right,arrive | - | a,c | ab,bc,bc | depart,turn left,arrive | + | a,d | ab,bd,bd | depart,on ramp right,arrive | + | a,c | ab,bc | depart,arrive | Scenario: Fork Slight Ramp Given the node map @@ -179,8 +179,8 @@ Feature: Ramp Guidance When I route I should get | waypoints | route | turns | - | a,d | ab,bd,bd | depart,on ramp slight right,arrive | - | a,c | ab,bc,bc | depart,turn slight left,arrive | + | a,d | ab,bd,bd | depart,on ramp slight right,arrive | + | a,c | ab,bc | depart,arrive | Scenario: Fork Slight Ramp on Through Street Given the node map diff --git a/features/guidance/roundabout.feature b/features/guidance/roundabout.feature index 3b5610dcd..5245c310a 100644 --- a/features/guidance/roundabout.feature +++ b/features/guidance/roundabout.feature @@ -791,10 +791,10 @@ Feature: Basic Roundabout # the turn angles here are quite strange, so we do get uturns for exiting When I route I should get | from | to | route | turns | distance | - | e | f | ed,af,af,af | depart,roundabout-exit-1,exit roundabout left,arrive | 80.1m | - | f | e | af,ed,ed,ed | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120.1m | - | k | l | kg,hl,hl,hl | depart,roundabout-exit-1,exit roundabout right,arrive | 80.1m | - | l | k | hl,kg,kg,kg | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120.1m | + | e | f | ed,af,af,af | depart,roundabout-exit-1,exit roundabout left,arrive | 80m | + | f | e | af,ed,ed,ed | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120m | + | k | l | kg,hl,hl,hl | depart,roundabout-exit-1,exit roundabout right,arrive | 80m | + | l | k | hl,kg,kg,kg | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120m | @4030 @4075 Scenario: Service roundabout with service exits @@ -846,5 +846,5 @@ Feature: Basic Roundabout When I route I should get | from | to | route | turns | distance | - | e | k | ebds,ufghl,ufghl,jhik,jhik | depart,rstur-exit-2,exit rotary right,turn right,arrive | 189.1m | + | e | k | ebds,ufghl,ufghl,jhik,jhik | depart,rstur-exit-2,exit rotary right,turn right,arrive | 189.2m | | 1 | k | ebds,ufghl,ufghl,jhik,jhik | depart,rstur-exit-2,exit rotary right,turn right,arrive | 159.1m | diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index f34774e9e..1db63bfcb 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -836,9 +836,9 @@ Feature: Turn Lane Guidance | cf | secondary | bottom | | When I route I should get - | waypoints | turns | route | lanes | - | a,d | depart,continue right,continue right,arrive | road,road,road,road | ,straight:false right:true,, | - | d,a | depart,continue left,continue left,arrive | road,road,road,road | ,left:true straight:false,, | + | waypoints | turns | route | lanes | + | a,d | depart,continue uturn,arrive | road,road,road | ,straight:false right:true;, | + | d,a | depart,continue uturn,arrive | road,road,road | ,left:true straight:false;, | @simple Scenario: Merge Lanes Onto Freeway diff --git a/features/raster/extract.feature b/features/raster/extract.feature index 8f2514aef..ad35b9bac 100644 --- a/features/raster/extract.feature +++ b/features/raster/extract.feature @@ -20,6 +20,6 @@ Feature: osrm-extract with a profile containing raster source And the data has been saved to disk When I run "osrm-extract {osm_file} -p {profile_file}" Then stdout should contain "source loader" - Then stdout should contain "slope: 0.0899" - Then stdout should contain "slope: -0.0899" + Then stdout should contain "slope: 0.0904" + Then stdout should contain "slope: -0.0904" And it should exit successfully diff --git a/features/step_definitions/routability.js b/features/step_definitions/routability.js index 93aa9e41c..7c9c55d8f 100644 --- a/features/step_definitions/routability.js +++ b/features/step_definitions/routability.js @@ -1,6 +1,6 @@ -var util = require('util'); -var d3 = require('d3-queue'); -var classes = require('../support/data_classes'); +const util = require('util'); +const d3 = require('d3-queue'); +const classes = require('../support/data_classes'); module.exports = function () { this.Then(/^routability should be$/, (table, callback) => { @@ -115,8 +115,11 @@ module.exports = function () { var result = {}; var testDirection = (dir, callback) => { - var a = new classes.Location(this.origin[0] + (1+this.WAY_SPACING*i) * this.zoom, this.origin[1]), - b = new classes.Location(this.origin[0] + (3+this.WAY_SPACING*i) * this.zoom, this.origin[1]), + const coordA = this.offsetOriginBy(1+this.WAY_SPACING*i, 0); + const coordB = this.offsetOriginBy(3+this.WAY_SPACING*i, 0); + + var a = new classes.Location(coordA[0], coordA[1]), + b = new classes.Location(coordB[0], coordB[1]), r = {}; r.which = dir; diff --git a/features/support/data.js b/features/support/data.js index e9e1f06f4..6dd5fc545 100644 --- a/features/support/data.js +++ b/features/support/data.js @@ -9,17 +9,27 @@ const classes = require('./data_classes'); const tableDiff = require('../lib/table_diff'); const ensureDecimal = require('../lib/utils').ensureDecimal; const errorReason = require('../lib/utils').errorReason; +const CheapRuler = require('cheap-ruler'); module.exports = function () { this.setGridSize = (meters) => { + this.gridSize = parseFloat(meters); + // the constant is calculated (with BigDecimal as: 1.0/(DEG_TO_RAD*EARTH_RADIUS_IN_METERS // see ApproximateDistance() in ExtractorStructs.h // it's only accurate when measuring along the equator, or going exactly north-south - this.zoom = parseFloat(meters) * 0.8990679362704610899694577444566908445396483347536032203503E-5; + this.zoom = this.gridSize * 0.8990679362704610899694577444566908445396483347536032203503E-5; }; this.setOrigin = (origin) => { this.origin = origin; + // we use C++ version of `cheap-ruler` inside OSRM in order to do distance calculations, + // so here we use it too to have a bit more precise assertions + this.ruler = new CheapRuler(this.origin[1], 'meters'); + }; + + this.offsetOriginBy = (xCells, yCells) => { + return this.ruler.offset(this.origin, xCells * this.gridSize, yCells * this.gridSize); }; this.buildWaysFromTable = (table, callback) => { @@ -35,9 +45,10 @@ module.exports = function () { // add some nodes var makeFakeNode = (namePrefix, offset) => { + const coord = this.offsetOriginBy(offset + this.WAY_SPACING * ri, 0); return new OSM.Node(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, - this.OSM_UID, this.origin[0]+(offset + this.WAY_SPACING * ri) * this.zoom, - this.origin[1], {name: util.format('%s%d', namePrefix, ri)}); + this.OSM_UID, coord[0], + coord[1], {name: util.format('%s%d', namePrefix, ri)}); }; var nodes = ['a','b','c','d','e'].map((l, i) => makeFakeNode(l, i)); @@ -98,7 +109,7 @@ module.exports = function () { }; this.tableCoordToLonLat = (ci, ri) => { - return [this.origin[0] + ci * this.zoom, this.origin[1] - ri * this.zoom].map(ensureDecimal); + return this.offsetOriginBy(ci, -ri).map(ensureDecimal); }; this.addOSMNode = (name, lon, lat, id) => { diff --git a/features/testbot/annotations.feature b/features/testbot/annotations.feature index 706eb9504..5e31be73a 100644 --- a/features/testbot/annotations.feature +++ b/features/testbot/annotations.feature @@ -115,4 +115,4 @@ Feature: Annotations When I route I should get | from | to | route | a:speed | a:distance | a:duration | a:nodes | - | a | c | abc,abc | 10:10 | 249.998641:299.931643 | 25:30 | 1:2:3 | + | a | c | abc,abc | 10:10 | 249.987619:299.962882 | 25:30 | 1:2:3 | diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature index ec6708a70..227324bff 100644 --- a/features/testbot/bearing_param.feature +++ b/features/testbot/bearing_param.feature @@ -108,12 +108,12 @@ Feature: Bearing parameter | ha | yes | ring | When I route I should get - | from | to | bearings | route | bearing | - | 0 | q | 0 90 | ia,ring,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,0->90,90->0 | - | 0 | a | 45 90 | jb,ring,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,0->90,90->0 | - | 0 | q | 90 90 | kc,ring,ring,ring,ring | 0->90,90->180,270->0,0->90,90->0 | - | 0 | a | 135 90 | ld,ring,ring,ring,ring | 0->135,135->270,270->0,0->90,90->0 | - | 0 | a | 180 90 | me,ring,ring,ring,ring | 0->180,180->270,270->0,0->90,90->0 | - | 0 | a | 225 90 | nf,ring,ring,ring | 0->225,225->0,0->90,90->0 | - | 0 | a | 270 90 | og,ring,ring,ring | 0->270,270->0,0->90,90->0 | - | 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 | + | from | to | bearings | route | bearing | + | 0 | q | 0 90 | ia,ring,ring,ring,ring,ring,ring | 0->0,0->90,90->180,180->270,270->0,0->90,90->0 | + | 0 | a | 45 90 | jb,ring,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,0->90,90->0 | + | 0 | q | 90 90 | kc,ring,ring,ring,ring,ring | 0->90,90->180,180->270,270->0,0->90,90->0 | + | 0 | a | 135 90 | ld,ring,ring,ring,ring | 0->135,135->270,270->0,0->90,90->0 | + | 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,0->90,90->0 | + | 0 | a | 225 90 | nf,ring,ring,ring | 0->225,225->0,0->90,90->0 | + | 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 | + | 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 | diff --git a/features/testbot/compression.feature b/features/testbot/compression.feature index 033cc3335..da8c0cdef 100644 --- a/features/testbot/compression.feature +++ b/features/testbot/compression.feature @@ -20,5 +20,5 @@ Feature: Geometry Compression When I route I should get | from | to | route | distance | speed | - | b | e | abcdef,abcdef | 588.5m | 36 km/h | - | e | b | abcdef,abcdef | 588.5m | 36 km/h | + | b | e | abcdef,abcdef | 588.7m | 36 km/h | + | e | b | abcdef,abcdef | 588.7m | 36 km/h | diff --git a/features/testbot/distance.feature b/features/testbot/distance.feature index 1b76f45a6..50595b087 100644 --- a/features/testbot/distance.feature +++ b/features/testbot/distance.feature @@ -90,8 +90,8 @@ Feature: Distance calculation | b | a | abc,abc | 100m | | b | c | abc,abc | 100m | | c | b | abc,abc | 100m | - | a | c | abc,abc | 200m | - | c | a | abc,abc | 200m | + | a | c | abc,abc | 199.9m | + | c | a | abc,abc | 199.9m | Scenario: 1km distance Given a grid size of 1000 meters @@ -134,7 +134,7 @@ Feature: Distance calculation | a | c | abcdefgh,abcdefgh | 20m | | a | d | abcdefgh,abcdefgh | 30m | | a | e | abcdefgh,abcdefgh | 40m | - | a | f | abcdefgh,abcdefgh | 50m | + | a | f | abcdefgh,abcdefgh | 50.1m | | a | g | abcdefgh,abcdefgh | 60m +-1 | | a | h | abcdefgh,abcdefgh | 70m +-1 | @@ -154,9 +154,9 @@ Feature: Distance calculation | from | to | route | distance | | a | b | abcdefgh,abcdefgh | 10m | | a | c | abcdefgh,abcdefgh | 20m | - | a | d | abcdefgh,abcdefgh | 30m | - | a | e | abcdefgh,abcdefgh | 40m | - | a | f | abcdefgh,abcdefgh | 50m | + | a | d | abcdefgh,abcdefgh | 29.9m | + | a | e | abcdefgh,abcdefgh | 39.9m | + | a | f | abcdefgh,abcdefgh | 49.9m | | a | g | abcdefgh,abcdefgh | 60m +-1 | | a | h | abcdefgh,abcdefgh | 70m +-1 | diff --git a/features/testbot/distance_matrix.feature b/features/testbot/distance_matrix.feature index 6ac1ce21b..c1340146f 100644 --- a/features/testbot/distance_matrix.feature +++ b/features/testbot/distance_matrix.feature @@ -22,10 +22,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | - | b | 100.1 | 0 | 99.4 | 199.5 | - | e | 199.5 | 99.4 | 0 | 100.1 | - | f | 299.5 | 199.5 | 100.1 | 0 | + | a | 0 | 100 | 199.9 | 300 | + | b | 100 | 0 | 100 | 200 | + | e | 199.9 | 100 | 0 | 100.1 | + | f | 300 | 200 | 100.1 | 0 | Scenario: Testbot - Travel distance matrix of minimal network exact distances Given the node map @@ -43,11 +43,11 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | z | b | c | d | - | a | 0 | 100.1 | 199.5 | 298.9 | 398.3 | - | z | 100.1 | 0 | 99.4 | 198.8 | 298.2 | - | b | 199.5 | 99.4 | 0 | 99.4 | 198.8 | - | c | 298.9 | 198.8 | 99.4 | 0 | 99.4 | - | d | 398.3 | 298.2 | 198.8 | 99.4 | 0 | + | a | 0 | 100 | 199.9 | 300 | 399.9 | + | z | 100 | 0 | 100 | 200 | 300 | + | b | 199.9 | 100 | 0 | 100.1 | 200 | + | c | 300 | 200 | 100.1 | 0 | 100 | + | d | 399.9 | 300 | 200 | 100 | 0 | Scenario: Testbot - Travel distance matrix of minimal network with toll exclude Given the query options @@ -68,10 +68,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 100.1 | | | - | b | 100.1 | 0 | | | - | c | | | 0 | 100.1 | - | d | | | 100.1 | 0 | + | a | 0 | 100 | | | + | b | 100 | 0 | | | + | c | | | 0 | 100 | + | d | | | 100 | 0 | Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude Given the query options @@ -92,7 +92,7 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 298.9 | 99.4 | 199.5 | + | a | 0 | 299.9 | 100 | 199.9 | Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude Given the query options @@ -113,7 +113,7 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | e | - | a | 0 | 50.1 | | + | a | 0 | 50 | | Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes Given the query options @@ -134,7 +134,7 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | e | g | - | a | 0 | 100.1 | | | + | a | 0 | 100 | | | Scenario: Testbot - Travel distance matrix with different way speeds Given the node map @@ -150,21 +150,21 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 100.1 | 200.1 | 300.2 | - | b | 100.1 | 0 | 100.1 | 200.1 | - | c | 200.1 | 100.1 | 0 | 100.1 | - | d | 300.2 | 200.1 | 100.1 | 0 | + | a | 0 | 100 | 200 | 300 | + | b | 100 | 0 | 100.1 | 200 | + | c | 200 | 100.1 | 0 | 100 | + | d | 300 | 200 | 100 | 0 | When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 100.1 | 200.1 | 300.2 | + | a | 0 | 100 | 200 | 300 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 100.1 | - | c | 200.1 | - | d | 300.2 | + | b | 100 | + | c | 200 | + | d | 300 | Scenario: Testbot - Travel distance matrix of small grid Given the node map @@ -183,10 +183,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | - | b | 100.1 | 0 | 99.4 | 199.5 | - | e | 199.5 | 99.4 | 0 | 100.1 | - | f | 299.5 | 199.5 | 100.1 | 0 | + | a | 0 | 100 | 199.9 | 300 | + | b | 100 | 0 | 100 | 200 | + | e | 199.9 | 100 | 0 | 100.1 | + | f | 300 | 200 | 100.1 | 0 | Scenario: Testbot - Travel distance matrix of network with unroutable parts Given the node map @@ -200,7 +200,7 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | - | a | 0 | 100.1 | + | a | 0 | 100 | | b | | 0 | Scenario: Testbot - Travel distance matrix of network with oneways @@ -218,10 +218,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | x | y | d | e | - | x | 0 | 300.2 | 399.6 | 299.5 | - | y | 499 | 0 | 299.5 | 199.5 | - | d | 199.5 | 299.5 | 0 | 298.9 | - | e | 299.5 | 399.6 | 100.1 | 0 | + | x | 0 | 300 | 400 | 300 | + | y | 499.9 | 0 | 300 | 199.9 | + | d | 199.9 | 300 | 0 | 300 | + | e | 300 | 400 | 100.1 | 0 | Scenario: Testbot - Rectangular travel distance matrix Given the node map @@ -240,53 +240,53 @@ Feature: Basic Distance Matrix When I route I should get | from | to | distance | - | e | a | 200m | + | e | a | 199.9m | | e | b | 100m | - | f | a | 299.9m | + | f | a | 300m | | f | b | 200m | When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | + | a | 0 | 100 | 199.9 | 300 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 100.1 | - | e | 199.5 | - | f | 299.5 | + | b | 100 | + | e | 199.9 | + | f | 300 | When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | - | b | 100.1 | 0 | 99.4 | 199.5 | + | a | 0 | 100 | 199.9 | 300 | + | b | 100 | 0 | 100 | 200 | When I request a travel distance matrix I should get | | a | b | - | a | 0 | 100.1 | - | b | 100.1 | 0 | - | e | 199.5 | 99.4 | - | f | 299.5 | 199.5 | + | a | 0 | 100 | + | b | 100 | 0 | + | e | 199.9 | 100 | + | f | 300 | 200 | When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | - | b | 100.1 | 0 | 99.4 | 199.5 | - | e | 199.5 | 99.4 | 0 | 100.1 | + | a | 0 | 100 | 199.9 | 300 | + | b | 100 | 0 | 100 | 200 | + | e | 199.9 | 100 | 0 | 100.1 | When I request a travel distance matrix I should get | | a | b | e | - | a | 0 | 100.1 | 199.5 | - | b | 100.1 | 0 | 99.4 | - | e | 199.5 | 99.4 | 0 | - | f | 299.5 | 199.5 | 100.1 | + | a | 0 | 100 | 199.9 | + | b | 100 | 0 | 100 | + | e | 199.9 | 100 | 0 | + | f | 300 | 200 | 100.1 | When I request a travel distance matrix I should get | | a | b | e | f | - | a | 0 | 100.1 | 199.5 | 299.5 | - | b | 100.1 | 0 | 99.4 | 199.5 | - | e | 199.5 | 99.4 | 0 | 100.1 | - | f | 299.5 | 199.5 | 100.1 | 0 | + | a | 0 | 100 | 199.9 | 300 | + | b | 100 | 0 | 100 | 200 | + | e | 199.9 | 100 | 0 | 100.1 | + | f | 300 | 200 | 100.1 | 0 | Scenario: Testbot - Travel distance 3x2 matrix Given the node map @@ -306,8 +306,8 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | b | e | f | - | a | 100.1 | 199.5 | 299.5 | - | b | 0 | 99.4 | 199.5 | + | a | 100 | 199.9 | 300 | + | b | 0 | 100 | 200 | Scenario: Testbot - All coordinates are from same small component Given a grid size of 300 meters @@ -328,8 +328,8 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | f | g | - | f | 0 | 298.2 | - | g | 298.2 | 0 | + | f | 0 | 300 | + | g | 300 | 0 | Scenario: Testbot - Coordinates are from different small component and snap to big CC Given a grid size of 300 meters @@ -362,10 +362,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | f | g | h | i | - | f | 0 | 298.2 | 0 | 298.2 | - | g | 298.2 | 0 | 298.2 | 0 | - | h | 0 | 298.2 | 0 | 298.2 | - | i | 298.2 | 0 | 298.2 | 0 | + | f | 0 | 300 | 0 | 300 | + | g | 300 | 0 | 300 | 0 | + | h | 0 | 300 | 0 | 300 | + | i | 300 | 0 | 300 | 0 | Scenario: Testbot - Travel distance matrix with loops Given the node map @@ -383,10 +383,10 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | 1 | 2 | 3 | 4 | - | 1 | 0 | 100.1 | 399.6 | 499.7 | - | 2 | 699.1 | 0 | 299.5 | 399.6 | - | 3 | 399.6 | 499.7 | 0 | 100.1 | - | 4 | 299.5 | 399.6 | 699.1 | 0 | + | 1 | 0 | 100.1 | 399.9 | 500 | + | 2 | 699.8 | 0 | 299.9 | 399.9 | + | 3 | 399.9 | 500 | 0 | 100.1 | + | 4 | 299.9 | 399.9 | 699.8 | 0 | Scenario: Testbot - Travel distance matrix based on segment durations @@ -424,11 +424,11 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | e | - | a | 0 | 100.1 | 200.1 | 300.2 | 398.9 | - | b | 100.1 | 0 | 100.1 | 200.1 | 298.9 | - | c | 200.1 | 100.1 | 0 | 100.1 | 198.8 | - | d | 300.2 | 200.1 | 100.1 | 0 | 298.9 | - | e | 398.9 | 298.9 | 198.8 | 298.9 | 0 | + | a | 0 | 100 | 200 | 300 | 400 | + | b | 100 | 0 | 100.1 | 200 | 300.1 | + | c | 200 | 100.1 | 0 | 100 | 200 | + | d | 300 | 200 | 100 | 0 | 300 | + | e | 400 | 300.1 | 200 | 300 | 0 | Scenario: Testbot - Travel distance matrix for alternative loop paths Given the profile file @@ -468,25 +468,25 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - | 1 | 0 | 1096.7 | 298.9 | 199.5 | 598.4 | 498.3 | 897.3 | 797.9 | - | 2 | 100.1 | 0 | 398.9 | 299.5 | 698.5 | 598.4 | 997.3 | 897.9 | - | 3 | 897.9 | 797.9 | 0 | 1097.4 | 299.5 | 199.5 | 598.4 | 499 | - | 4 | 997.3 | 897.3 | 99.4 | 0 | 398.9 | 298.9 | 697.8 | 598.4 | - | 5 | 598.4 | 498.3 | 897.3 | 797.9 | 0 | 1096.7 | 298.9 | 199.5 | - | 6 | 698.5 | 598.4 | 997.3 | 897.9 | 100.1 | 0 | 398.9 | 299.5 | - | 7 | 299.5 | 199.5 | 598.4 | 499 | 897.9 | 797.9 | 0 | 1097.4 | - | 8 | 398.9 | 298.9 | 697.8 | 598.4 | 997.3 | 897.3 | 99.4 | 0 | + | 1 | 0 | 1099.8 | 300 | 199.9 | 600 | 499.9 | 899.9 | 799.9 | + | 2 | 100.1 | 0 | 400 | 300 | 700 | 600 | 1000 | 899.9 | + | 3 | 899.9 | 799.9 | 0 | 1099.8 | 300 | 199.9 | 600 | 499.9 | + | 4 | 1000 | 899.9 | 100.1 | 0 | 400 | 300 | 700 | 600 | + | 5 | 600 | 499.9 | 899.9 | 799.9 | 0 | 1099.8 | 300 | 199.9 | + | 6 | 700 | 600 | 1000 | 899.9 | 100.1 | 0 | 400 | 300 | + | 7 | 300 | 199.9 | 600 | 499.9 | 899.9 | 799.9 | 0 | 1099.8 | + | 8 | 400 | 300 | 700 | 600 | 1000 | 899.9 | 100.1 | 0 | When I request a travel distance matrix I should get | | 1 | | 1 | 0 | | 2 | 100.1 | - | 3 | 897.9 | - | 4 | 997.3 | - | 5 | 598.4 | - | 6 | 698.5 | - | 7 | 299.5 | - | 8 | 398.9 | + | 3 | 899.9 | + | 4 | 1000 | + | 5 | 600 | + | 6 | 700 | + | 7 | 300 | + | 8 | 400 | Scenario: Testbot - Travel distance matrix with ties Given the node map @@ -511,23 +511,23 @@ Feature: Basic Distance Matrix | from | to | route | distance | | a | b | ab,ab | 450m | | a | c | ac,ac | 200m | - | a | d | ac,dc,dc | 499.9m | + | a | d | ac,dc,dc | 500m | When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 450.3 | 198.8 | 499 | + | a | 0 | 450 | 200 | 500 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 450.3 | - | c | 198.8 | - | d | 499 | + | b | 450 | + | c | 200 | + | d | 500 | When I request a travel distance matrix I should get | | a | c | - | a | 0 | 198.8 | - | c | 198.8 | 0 | + | a | 0 | 200 | + | c | 200 | 0 | # Check rounding errors @@ -544,7 +544,7 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | - | a | 0 | 1000.7 | 2001.4 | 3002.1 | + | a | 0 | 1000.1 | 2000 | 3000.1 | Scenario: Testbot - OneToMany vs ManyToOne @@ -562,12 +562,12 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | - | b | 240.4 | 0 | + | b | 241.3 | 0 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 240.4 | + | b | 241.3 | Scenario: Testbot - Varying distances between nodes Given the node map @@ -589,12 +589,13 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | c | d | e | f | - | a | 0 | 100.1 | 300.2 | 650.5 | 1930.6 | 1533 | - | b | 759 | 0 | 200.1 | 550.4 | 1830.5 | 1432.9 | - | c | 558.8 | 658.9 | 0 | 350.3 | 1630.4 | 1232.8 | - | d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 | - | e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 | - | f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 | + | a | 0 | 100 | 300 | 650 | 1934.5 | 1534.6 | + | b | 760.6 | 0 | 200 | 550.1 | 1834.6 | 1434.6 | + | c | 560.6 | 660.5 | 0 | 350 | 1634.6 | 1234.6 | + | d | 1484.6 | 1584.5| 1784.5 | 0 | 1284.5 | 884.6 | + | e | 200 | 300 | 500 | 710.6 | 0 | 1595.2 | + | f | 600 | 699.9 | 899.9 | 1110.5 | 399.9 | 0 | + Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location) Given a grid size of 300 meters @@ -614,21 +615,21 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1501.1 | - | b | 300.2 | 0 | 600.5 | 1200.9 | - | f | 900.7 | 600.5 | 0 | 300.2 | - | 1 | 1501.1 | 1200.9 | 300.2 | 0 | + | a | 0 | 300 | 900 | 1500 | + | b | 300 | 0 | 600 | 1200.1 | + | f | 900 | 600 | 0 | 300 | + | 1 | 1500 | 1200.1 | 300 | 0 | When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1501.1 | + | a | 0 | 300 | 900 | 1500 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 300.2 | - | f | 900.7 | - | 1 | 1501.1 | + | b | 300 | + | f | 900 | + | 1 | 1500 | Scenario: Testbot - Fise input coordinate Given a grid size of 300 meters @@ -649,21 +650,21 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1501.1 | - | b | 300.2 | 0 | 600.5 | 1200.9 | - | f | 900.7 | 600.5 | 0 | 300.2 | - | 1 | 1501.1 | 1200.9 | 300.2 | 0 | + | a | 0 | 300 | 900 | 1500 | + | b | 300 | 0 | 600 | 1200.1 | + | f | 900 | 600 | 0 | 300 | + | 1 | 1500 | 1200.1 | 300 | 0 | When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1501.1 | + | a | 0 | 300 | 900 | 1500 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 300.2 | - | f | 900.7 | - | 1 | 1501.1 | + | b | 300 | + | f | 900 | + | 1 | 1500 | Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate @@ -685,28 +686,28 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1200.9 | - | b | 300.2 | 0 | 600.5 | 900.7 | - | f | 900.7 | 600.5 | 0 | 300.2 | - | 1 | 1200.9 | 900.7 | 300.2 | 0 | + | a | 0 | 300 | 900 | 1200 | + | b | 300 | 0 | 600 | 900 | + | f | 900 | 600 | 0 | 300 | + | 1 | 1200 | 900 | 300 | 0 | When I request a travel distance matrix I should get | | a | b | f | 1 | - | a | 0 | 300.2 | 900.7 | 1200.9 | + | a | 0 | 300 | 900 | 1200 | When I request a travel distance matrix I should get | | a | | a | 0 | - | b | 300.2 | - | f | 900.7 | - | 1 | 1200.9 | + | b | 300 | + | f | 900 | + | 1 | 1200 | Scenario: Ensure consistency with route, and make sure offsets work in both directions Given a grid size of 100 meters Given the node map """ a b c d e f g h i j - 1 2 + 1 2 3 """ And the ways @@ -715,11 +716,14 @@ Feature: Basic Distance Matrix | fghij | When I route I should get - | from | to | route | distance | - | 1 | 2 | abcdef,fghij,fghij | 999.9m | + | from | to | route | distance | + | 1 | 2 | abcdef,fghij,fghij | 1000.1m | + | 1 | 3 | abcdef,fghij,fghij | 1400.1m | + | 2 | 3 | fghij,fghij | 400m | + - # TODO: this is "correct", but inconsistent with viaroute When I request a travel distance matrix I should get - | | 1 | 2 | - | 1 | 0 | 1000.7 | - | 2 | 1000.7 | 0 | \ No newline at end of file + | | 1 | 2 | 3 | + | 1 | 0 | 1000.1 | 1400.1 | + | 2 | 1000.1 | 0 | 400 | + | 3 | 1400.1 | 400 | 0 | \ No newline at end of file diff --git a/features/testbot/duration_matrix.feature b/features/testbot/duration_matrix.feature index 94e0a6414..28ffaaed3 100644 --- a/features/testbot/duration_matrix.feature +++ b/features/testbot/duration_matrix.feature @@ -446,15 +446,15 @@ Feature: Basic Duration Matrix | ca | yes | When I request a travel time matrix I should get - | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - | 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 | - | 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 | - | 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 | - | 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 | - | 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 | - | 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 | - | 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 | - | 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 | + | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + | 1 | 0 | 10.9 | 3 | 1.9 | 6 | 4.9 | 9 | 7.9 | + | 2 | 1.1 | 0 | 4.1 | 3 | 7.1 | 6 | 10.1 | 9 | + | 3 | 9 | 7.9 | 0 | 10.9 | 3 | 1.9 | 6 | 4.9 | + | 4 | 10.1 | 9 | 1.1 | 0 | 4.1 | 3 | 7.1 | 6 | + | 5 | 6 | 4.9 | 9 | 7.9 | 0 | 10.9 | 3 | 1.9 | + | 6 | 7.1 | 6 | 10.1 | 9 | 1.1 | 0 | 4.1 | 3 | + | 7 | 3 | 1.9 | 6 | 4.9 | 9 | 7.9 | 0 | 10.9 | + | 8 | 4.1 | 3 | 7.1 | 6 | 10.1 | 9 | 1.1 | 0 | Scenario: Testbot - Travel time matrix with ties @@ -543,22 +543,22 @@ Feature: Basic Duration Matrix | fhigf | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 30 | - | b | 30 | 0 | 12 | 24 | - | f | 18 | 12 | 0 | 30 | - | 1 | 30 | 24 | 30 | 0 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 30 | + | b | 30 | 0 | 12 | 24 | + | f | 17.9 | 12 | 0 | 30 | + | 1 | 30 | 24 | 30 | 0 | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 30 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 30 | When I request a travel time matrix I should get - | | a | - | a | 0 | - | b | 30 | - | f | 18 | - | 1 | 30 | + | | a | + | a | 0 | + | b | 30 | + | f | 17.9 | + | 1 | 30 | When I request a travel time matrix I should get estimates for | | a | b | f | 1 | @@ -596,22 +596,22 @@ Feature: Basic Duration Matrix | fhigf | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 30 | - | b | 30 | 0 | 12 | 24 | - | f | 18 | 12 | 0 | 30 | - | 1 | 30 | 24 | 30 | 0 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 30 | + | b | 30 | 0 | 12 | 24 | + | f | 17.9 | 12 | 0 | 30 | + | 1 | 30 | 24 | 30 | 0 | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 30 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 30 | When I request a travel time matrix I should get - | | a | - | a | 0 | - | b | 30 | - | f | 18 | - | 1 | 30 | + | | a | + | a | 0 | + | b | 30 | + | f | 17.9 | + | 1 | 30 | When I request a travel time matrix I should get estimates for | | a | b | f | 1 | @@ -650,22 +650,22 @@ Feature: Basic Duration Matrix | fhigf | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 24 | - | b | 30 | 0 | 12 | 18 | - | f | 18 | 12 | 0 | 30 | - | 1 | 24 | 18 | 30 | 0 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 23.9 | + | b | 30 | 0 | 12 | 17.9 | + | f | 17.9 | 12 | 0 | 30 | + | 1 | 23.9 | 17.9 | 30 | 0 | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 30 | 18 | 24 | + | | a | b | f | 1 | + | a | 0 | 30 | 17.9 | 23.9 | When I request a travel time matrix I should get - | | a | - | a | 0 | - | b | 30 | - | f | 18 | - | 1 | 24 | + | | a | + | a | 0 | + | b | 30 | + | f | 17.9 | + | 1 | 23.9 | When I request a travel time matrix I should get estimates for | | a | b | f | 1 | @@ -719,22 +719,22 @@ Feature: Basic Duration Matrix | fhigf | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 60 | 36 | 48 | - | b | 60 | 0 | 24 | 36 | - | f | 36 | 24 | 0 | 60 | - | 1 | 48 | 36 | 60 | 0 | + | | a | b | f | 1 | + | a | 0 | 60 | 35.8 | 47.8 | + | b | 60 | 0 | 24 | 35.8 | + | f | 35.8 | 24 | 0 | 60 | + | 1 | 47.8 | 35.8 | 60 | 0 | When I request a travel time matrix I should get - | | a | b | f | 1 | - | a | 0 | 60 | 36 | 48 | + | | a | b | f | 1 | + | a | 0 | 60 | 35.8 | 47.8 | When I request a travel time matrix I should get - | | a | - | a | 0 | - | b | 60 | - | f | 36 | - | 1 | 48 | + | | a | + | a | 0 | + | b | 60 | + | f | 35.8 | + | 1 | 47.8 | When I request a travel time matrix I should get estimates for | | a | b | f | 1 | diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature index 599afcb1d..f8e1b2738 100644 --- a/features/testbot/matching.feature +++ b/features/testbot/matching.feature @@ -279,8 +279,8 @@ Feature: Basic Map Matching | fb | yes | When I match I should get - | trace | matchings | geometry | - | efbc | efbc | 1,0.99964,1.00036,0.99964,1.00036,1,1.000719,1 | + | trace | matchings | geometry | + | efbc | efbc | 1,0.999638,1.000359,0.999638,1.000359,1,1.000719,1 | Scenario: Testbot - Geometry details using geojson Given the query options @@ -356,7 +356,7 @@ Feature: Basic Map Matching When I match I should get | trace | matchings | alternatives | - | abcdef | abcde | 0,0,0,0,1,1 | + | abcdef | abcde | 0,0,0,1,1,1 | Scenario: Testbot - Speed greater than speed threshold Given a grid size of 100 meters @@ -652,7 +652,7 @@ Feature: Basic Map Matching When I match I should get | trace | geometry | code | - | defgh | 1,1,1,0.999461,1.000674,0.999461 | Ok | + | defgh | 1,1,1,0.999457,1.000674,0.999457 | Ok | @match @testbot Scenario: Regression test - waypoints trimming too much geometry @@ -682,8 +682,8 @@ Feature: Basic Map Matching | waypoints | 0;3 | | overview | full | When I match I should get - | trace | geometry | code | - | bgkj | 1.000135,1,1.000135,0.99964,1.000387,0.999137 | Ok | + | trace | geometry | code | + | bgkj | 1.000135,1,1.000135,0.999638,1.000386,0.999132 | Ok | @match @testbot @@ -712,12 +712,12 @@ Feature: Basic Map Matching | overview | full | | steps | true | When I match I should get - | trace | geometry | turns | code | - | abc | 1,0.99973,1.00027,0.99973,1.000539,0.99973 | depart,arrive | Ok | - | abd | 1,0.99973,1.00027,0.99973,1.00027,0.999461 | depart,turn right,arrive | Ok | - | abe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok | - | ahd | 1,0.99973,1.00027,0.99973,1.00027,0.999461 | depart,turn right,arrive | Ok | - | ahe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok | + | trace | geometry | turns | code | + | abc | 1,0.999729,1.000269,0.999729,1.000539,0.999729 | depart,arrive | Ok | + | abd | 1,0.999729,1.000269,0.999729,1.000269,0.999457 | depart,turn right,arrive | Ok | + | abe | 1,0.999729,1.000269,0.999729,1.000269,1 | depart,turn left,arrive | Ok | + | ahd | 1,0.999729,1.000269,0.999729,1.000269,0.999457 | depart,turn right,arrive | Ok | + | ahe | 1,0.999729,1.000269,0.999729,1.000269,1 | depart,turn left,arrive | Ok | @match @testbot Scenario: Regression test - add source phantoms properly (one phantom on one edge) @@ -740,9 +740,9 @@ Feature: Basic Map Matching | annotations | duration,weight | | generate_hints | false | When I match I should get - | trace | geometry | a:duration | a:weight | duration | - | 123 | 1.000135,1,1.000225,1,1.00036,1,1.000405,1,1.00045,1 | 1:1.5:0.5:0.5 | 1:1.5:0.5:0.5 | 3.5 | - | 321 | 1.00045,1,1.000405,1,1.00036,1,1.000225,1,1.000135,1 | 0.5:0.5:1.5:1 | 0.5:0.5:1.5:1 | 3.5 | + | trace | geometry | a:duration | a:weight | duration | + | 123 | 1.000135,1,1.000225,1,1.000359,1,1.000404,1,1.000449,1 | 1:1.5:0.5:0.4 | 1:1.5:0.5:0.4 | 3.4 | + | 321 | 1.000449,1,1.000404,1,1.000359,1,1.000225,1,1.000135,1 | 0.4:0.5:1.5:1 | 0.4:0.5:1.5:1 | 3.4 | @match @testbot Scenario: Regression test - add source phantom properly (two phantoms on one edge) @@ -765,9 +765,9 @@ Feature: Basic Map Matching | annotations | duration,weight | | generate_hints | false | When I match I should get - | trace | geometry | a:duration | a:weight | duration | - | 1234 | 1.000135,1,1.000225,1,1.000405,1,1.00045,1 | 1:2:0.5 | 1:2:0.5 | 3.5 | - | 4321 | 1.00045,1,1.000405,1,1.000225,1,1.000135,1 | 0.5:2:1 | 0.5:2:1 | 3.5 | + | trace | geometry | a:duration | a:weight | duration | + | 1234 | 1.000135,1,1.000225,1,1.000404,1,1.000449,1 | 1:2:0.4 | 1:2:0.4 | 3.4 | + | 4321 | 1.000449,1,1.000404,1,1.000225,1,1.000135,1 | 0.4:2:1 | 0.4:2:1 | 3.4 | @match @testbot Scenario: Regression test - add source phantom properly (two phantoms on one edge) @@ -791,5 +791,5 @@ Feature: Basic Map Matching # These should have the same weights/duration in either direction When I match I should get | trace | geometry | a:distance | a:duration | a:weight | duration | - | 2345 | 1.00018,1,1.000315,1 | 15.013264 | 1.5 | 1.5 | 1.5 | - | 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 | \ No newline at end of file + | 2345 | 1.00018,1,1.000314,1 | 14.914666 | 1.4 | 1.4 | 1.4 | + | 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 | \ No newline at end of file diff --git a/features/testbot/multi_level_routing.feature b/features/testbot/multi_level_routing.feature index 467ddd26f..5ffabec5e 100644 --- a/features/testbot/multi_level_routing.feature +++ b/features/testbot/multi_level_routing.feature @@ -110,33 +110,34 @@ Feature: Multi level routing When I request a travel distance matrix I should get | | a | f | l | o | - | a | 0 | 2383.7 | 1566.9 | 1366.8 | - | f | 2383.7 | 0 | 1293.3 | 1617.3 | - | l | 1566.9 | 1293.3 | 0 | 800.5 | - | o | 1366.8 | 1617.3 | 800.5 | 0 | + | a | 0 | 2391.6 | 1570.8 | 1370.9 | + | f | 2391.6 | 0 | 1297.2 | 1620.9 | + | l | 1570.8 | 1297.2 | 0 | 800 | + | o | 1370.9 | 1620.9 | 800 | 0 | + When I request a travel distance matrix I should get | | a | f | l | o | - | a | 0 | 2383.7 | 1566.9 | 1366.8 | + | a | 0 | 2391.6 | 1570.8 | 1370.9 | When I request a travel distance matrix I should get | | a | | a | 0 | - | f | 2383.7 | - | l | 1566.9 | - | o | 1366.8 | + | f | 2391.6 | + | l | 1570.8 | + | o | 1370.9 | When I request a travel distance matrix I should get | | a | f | l | o | - | a | 0 | 2383.7 | 1566.9 | 1366.8 | - | f | 2383.7 | 0 | 1293.3 | 1617.3 | + | a | 0 | 2391.6 | 1570.8 | 1370.9 | + | f | 2391.6 | 0 | 1297.2 | 1620.9 | When I request a travel distance matrix I should get | | a | o | - | a | 0 | 1366.8 | - | f | 2383.7 | 1617.3 | - | l | 1566.9 | 800.5 | - | o | 1366.8 | 0 | + | a | 0 | 1370.9 | + | f | 2391.6 | 1620.9 | + | l | 1570.8 | 800 | + | o | 1370.9 | 0 | Scenario: Testbot - Multi level routing: horizontal road Given the node map diff --git a/features/testbot/origin.feature b/features/testbot/origin.feature index c21febd07..fd14c86f7 100644 --- a/features/testbot/origin.feature +++ b/features/testbot/origin.feature @@ -53,7 +53,7 @@ Feature: Routing close to the [0,0] origin When I route I should get | from | to | route | distance | - | b | d | abcde,abcde | 200m | + | b | d | abcde,abcde | 198.8m | | d | b | | | Scenario: North-south oneways crossing the origin @@ -71,5 +71,5 @@ Feature: Routing close to the [0,0] origin When I route I should get | from | to | route | distance | - | b | d | abcde,abcde | 200m | + | b | d | abcde,abcde | 200.2m | | d | b | | | diff --git a/features/testbot/planetary.feature b/features/testbot/planetary.feature index 1fff4bded..c70cedb3d 100644 --- a/features/testbot/planetary.feature +++ b/features/testbot/planetary.feature @@ -26,8 +26,8 @@ Feature: Distance calculation | cd | When I route I should get - | from | to | route | distance | - | c | d | cd,cd | 6028844m ~4.5% | + | from | to | route | distance | + | c | d | cd,cd | 6310675.7m ~4.5% | Scenario: Approximated Longitudinal distances at latitude 80 Given the node locations @@ -54,8 +54,8 @@ Feature: Distance calculation | ab | When I route I should get - | from | to | route | distance | - | a | b | ab,ab | 8905559m ~0.1% | + | from | to | route | distance | + | a | b | ab,ab | 8882574.6m ~0.1% | Scenario: Approximated Latitudinal distances at longitude 45 Given the node locations @@ -68,8 +68,8 @@ Feature: Distance calculation | ab | When I route I should get - | from | to | route | distance | - | a | b | ab,ab | 8905559m ~0.1% | + | from | to | route | distance | + | a | b | ab,ab | 8882574.6m ~0.1% | Scenario: Approximated Latitudinal distances at longitude 80 Given the node locations @@ -83,4 +83,4 @@ Feature: Distance calculation When I route I should get | from | to | route | distance | - | a | b | ab,ab | 8905559m ~0.1% | + | a | b | ab,ab | 8882574.6m ~0.1% | diff --git a/features/testbot/projection.feature b/features/testbot/projection.feature index 49a5d8df1..c5bd6be18 100644 --- a/features/testbot/projection.feature +++ b/features/testbot/projection.feature @@ -23,13 +23,13 @@ Feature: Projection to nearest point on road Scenario: Projection onto way at high latitudes, 1km distance When I route I should get - | from | to | route | bearing | distance | - | b | a | abc,abc | 0->225,225->0 | 1000m | - | b | c | abc,abc | 0->45,45->0 | 1000m +- 3 | - | a | d | abc,abc | 0->45,45->0 | 1000m | - | d | a | abc,abc | 0->225,225->0 | 1000m | - | c | d | abc,abc | 0->225,225->0 | 1000m +- 3 | - | d | c | abc,abc | 0->45,45->0 | 1000m +- 3 | + | from | to | route | bearing | distance | + | b | a | abc,abc | 0->225,225->0 | 1002.9m | + | b | c | abc,abc | 0->45,45->0 | 1005m +- 3 | + | a | d | abc,abc | 0->45,45->0 | 1002.9m | + | d | a | abc,abc | 0->225,225->0 | 1002.9m | + | c | d | abc,abc | 0->225,225->0 | 1005m +- 3 | + | d | c | abc,abc | 0->45,45->0 | 1005m +- 3 | Scenario: Projection onto way at high latitudes, no distance When I route I should get diff --git a/features/testbot/traffic_speeds.feature b/features/testbot/traffic_speeds.feature index f5f2198f3..db3b2372b 100644 --- a/features/testbot/traffic_speeds.feature +++ b/features/testbot/traffic_speeds.feature @@ -48,13 +48,13 @@ Feature: Traffic - speeds When I route I should get | from | to | route | speed | weights | a:datasources | - | a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0 | - | a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 | - | b | c | bc,bc | 27 km/h | 741.5,0 | 1 | - | a | d | ad,ad | 27 km/h | 1275.7,0 | 1 | - | d | c | dc,dc | 36 km/h | 956.8,0 | 0 | - | g | b | fb,fb | 36 km/h | 164.7,0 | 0 | - | a | g | ad,df,fb,fb | 30 km/h | 1295.7,487.5,304.7,0 | 1:0:0 | + | a | b | ad,de,eb,eb | 30 km/h | 1273.9,400.8,378.5,0 | 1:0:0 | + | a | c | ad,dc,dc | 31 km/h | 1273.9,955.4,0 | 1:0 | + | b | c | bc,bc | 27 km/h | 737.2,0 | 1 | + | a | d | ad,ad | 27 km/h | 1273.9,0 | 1 | + | d | c | dc,dc | 36 km/h | 955.4,0 | 0 | + | g | b | fb,fb | 36 km/h | 164.4,0 | 0 | + | a | g | ad,df,fb,fb | 30 km/h | 1293.9,486.8,304.3,0 | 1:0:0 | Scenario: Weighting based on speed file weights, ETA based on file durations @@ -74,13 +74,13 @@ Feature: Traffic - speeds When I route I should get | from | to | route | speed | weights | a:datasources | - | a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0 | - | a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 | - | b | c | bc,bc | 27 km/h | 741.5,0 | 1 | - | a | d | ad,ad | 27 km/h | 1275.7,0 | 1 | - | d | c | dc,dc | 36 km/h | 956.8,0 | 0 | - | g | b | ab,ab | 1 km/h | 10010.4,0 | 1 | - | a | g | ab,ab | 1 km/h | 10010.3,0 | 1 | + | a | b | ad,de,eb,eb | 30 km/h | 1273.9,400.8,378.5,0 | 1:0:0 | + | a | c | ad,dc,dc | 31 km/h | 1273.9,955.4,0 | 1:0 | + | b | c | bc,bc | 27 km/h | 737.2,0 | 1 | + | a | d | ad,ad | 27 km/h | 1273.9,0 | 1 | + | d | c | dc,dc | 36 km/h | 955.4,0 | 0 | + | g | b | ab,ab | 1 km/h | 9951.7,0 | 1 | + | a | g | ab,ab | 1 km/h | 9951.7,0 | 1 | Scenario: Weighting based on speed file weights, ETA based on file durations @@ -106,14 +106,14 @@ Feature: Traffic - speeds When I route I should get | from | to | route | speed | weights | a:datasources | - | a | b | ab,ab | 1 km/h | 20020.73,0 | 1 | - | a | c | ab,bc,bc | 2 km/h | 20020.73,741.51,0 | 1:1 | - | b | c | bc,bc | 27 km/h | 741.51,0 | 1 | - | a | d | ab,eb,de,de | 2 km/h | 20020.73,378.17,400.41,0 | 1:0:0 | - | d | c | dc,dc | 36 km/h | 956.8,0 | 0 | - | g | b | ab,ab | 1 km/h | 10010.37,0 | 1 | - | a | g | ab,ab | 1 km/h | 10010.36,0 | 1 | - | g | a | ab,ab | 1 km/h | 10010.36,0 | 1 | + | a | b | ab,ab | 1 km/h | 19903.37,0 | 1 | + | a | c | ab,bc,bc | 2 km/h | 19903.37,737.16,0 | 1:1 | + | b | c | bc,bc | 27 km/h | 737.16,0 | 1 | + | a | d | ab,eb,de,de | 2 km/h | 19903.37,378.49,400.75,0 | 1:0:0 | + | d | c | dc,dc | 36 km/h | 955.45,0 | 0 | + | g | b | ab,ab | 1 km/h | 9951.69,0 | 1 | + | a | g | ab,ab | 1 km/h | 9951.68,0 | 1 | + | g | a | ab,ab | 1 km/h | 9951.68,0 | 1 | Scenario: Speeds that isolate a single node (a) @@ -136,13 +136,13 @@ Feature: Traffic - speeds When I route I should get | from | to | route | speed | weights | a:datasources | a:speed | a:nodes| - | a | b | fb,fb | 36 km/h | 329.4,0 | 0 | 10 | 6:2 | - | a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | 0:1 | 10:7.5 | 6:2:3 | - | b | c | bc,bc | 27 km/h | 741.5,0 | 1 | 7.5 | 2:3 | - | a | d | fb,df,df | 36 km/h | 140,487.5,0 | 0:0 | 10:10 | 2:6:4 | - | d | c | dc,dc | 36 km/h | 956.8,0 | 0 | 10 | 4:3 | - | g | b | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 | - | a | g | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 | + | a | b | fb,fb | 36 km/h | 328.9,0 | 0 | 10 | 6:2 | + | a | c | fb,bc,bc | 30 km/h | 328.9,737.2,0 | 0:1 | 10:7.5 | 6:2:3 | + | b | c | bc,bc | 27 km/h | 737.2,0 | 1 | 7.5 | 2:3 | + | a | d | fb,df,df | 36 km/h | 139.8,486.8,0 | 0:0 | 10:10 | 2:6:4 | + | d | c | dc,dc | 36 km/h | 955.4,0 | 0 | 10 | 4:3 | + | g | b | fb,fb | 36 km/h | 164.4,0 | 0 | 10 | 6:2 | + | a | g | fb,fb | 36 km/h | 164.5,0 | 0 | 10 | 6:2 | Scenario: Verify that negative values cause an error, they're not valid at all diff --git a/features/testbot/traffic_turn_penalties.feature b/features/testbot/traffic_turn_penalties.feature index 9d3c45412..4ab9aa8b2 100644 --- a/features/testbot/traffic_turn_penalties.feature +++ b/features/testbot/traffic_turn_penalties.feature @@ -62,8 +62,8 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap When I route I should get | from | to | route | speed | time | weights | | a | e | ab,be,be | 36 km/h | 40s +-1 | 16.7,20,0 | - | 1 | e | ab,be,be | 36 km/h | 30s +-1 | 6.7,20,0 | + | 1 | e | ab,be,be | 36 km/h | 30s +-1 | 6.8,20,0 | | b | f | bc,cf,cf | 36 km/h | 40s +-1 | 20,20,0 | - | 2 | f | bc,cf,cf | 36 km/h | 30s +-1 | 10,20,0 | + | 2 | f | bc,cf,cf | 36 km/h | 30s +-1 | 10.1,20,0 | | c | g | cd,dg,dg | 144 km/h | 10s +-1 | 120.8,20,0 | - | 3 | g | cd,dg,dg | 54 km/h | 20s +-1 | 110.8,20,0 | + | 3 | g | cd,dg,dg | 54 km/h | 20s +-1 | 110.9,20,0 | diff --git a/features/testbot/trip.feature b/features/testbot/trip.feature index c254f8d75..9fe3c23ae 100644 --- a/features/testbot/trip.feature +++ b/features/testbot/trip.feature @@ -221,7 +221,7 @@ Feature: Basic trip planning When I plan a trip I should get | waypoints | source | destination |roundtrip | trips | durations | distance | - | a,b,d,e,c | first | last | false | abedc | 8.200000000000001 | 81.6 | + | a,b,d,e,c | first | last | false | abedc | 8.200000000000001 | 81.4 | Scenario: Testbot - Trip: FSE with waypoints (more than 10) diff --git a/features/testbot/weight.feature b/features/testbot/weight.feature index eae35c0ff..5d8aadee3 100644 --- a/features/testbot/weight.feature +++ b/features/testbot/weight.feature @@ -28,12 +28,12 @@ Feature: Weight tests | cde | When I route I should get - | waypoints | route | a:weight | - | s,t | abc,cde | 1.1:2:2:1 | + | waypoints | route | a:weight | + | s,t | abc,cde | 1.1:2:2:0.9 | When I route I should get | waypoints | route | times | weight_name | weights | - | s,t | abc,cde | 6.1s,0s | duration | 6.1,0 | + | s,t | abc,cde | 6s,0s | duration | 6,0 | # FIXME include/engine/guidance/assemble_geometry.hpp:95 Scenario: Start and target on the same and adjacent edge @@ -53,10 +53,10 @@ Feature: Weight tests When I route I should get | waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed | - | s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 | - | t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 | - | s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | 9.7:10 | - | e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | 10:9.7 | + | s,t | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034627 | 2 | 2 | 10 | + | t,s | abc,abc | 20m,0m | 2,0 | 2s,0s | 20.034627 | 2 | 2 | 10 | + | s,e | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 29.940636:10.017313 | 3:0.9 | 3:0.9 | 10:11.1 | + | e,s | abc,abc | 40m,0m | 3.9,0 | 3.9s,0s | 10.017313:29.940636 | 0.9:3 | 0.9:3 | 11.1:10 | Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property @@ -173,13 +173,13 @@ Feature: Weight tests | fgh | When I route I should get - | waypoints | route | distance | weights | times | - | a,f | , | 100m | 99.9,0 | 30s,0s | - | f,a | , | 100m | 199.8,0 | 30s,0s | - | a,h | , | 140m | 139.9,0 | 42s,0s | - | h,a | , | 140m | 279.8,0 | 42s,0s | - | f,h | , | 40m | 40,0 | 12s,0s | - | h,f | , | 40m | 80,0 | 12s,0s | + | waypoints | route | distance | weights | times | + | a,f | , | 100m | 99.8,0 | 30s,0s | + | f,a | , | 100m | 199.9,0 | 30s,0s | + | a,h | , | 140m | 139.8,0 | 42s,0s | + | h,a | , | 140m | 280.1,0 | 42s,0s | + | f,h | , | 40.1m | 40,0 | 12s,0s | + | h,f | , | 40.1m | 80.2,0 | 12s,0s | Scenario: Step weights -- segment_function Given the profile file @@ -281,11 +281,11 @@ Feature: Weight tests When I route I should get | waypoints | route | distance | weights | times | - | a,c | , | 40m +-.1 | 5.119,0 | 289.9s,0s | - | a,e | ,, | 60m +-.1 | 5.119,1.11,0 | 289.9s,100s,0s | - | e,a | ,, | 60m +-.1 | 2.21,2.22,0 | 10.1s,200s,0s | - | e,d | ,, | 40m +-.1 | 4.009,1.11,0 | 189.9s,100s,0s | - | d,e | ,, | 40m +-.1 | 2.21,1.11,0 | 10.1s,100s,0s | + | a,c | , | 40m +-.1 | 5.12,0 | 290s,0s | + | a,e | ,, | 60m +-.1 | 5.12,1.11,0 | 290s,100s,0s | + | e,a | ,, | 60m +-.1 | 2.21,2.22,0 | 10s,200s,0s | + | e,d | ,, | 40m +-.1 | 4.01,1.11,0 | 190s,100s,0s | + | d,e | ,, | 40m +-.1 | 2.21,1.11,0 | 10s,100s,0s | @traffic @speed Scenario: Step weights -- segment_function with speed and turn updates @@ -341,9 +341,9 @@ Feature: Weight tests When I route I should get | waypoints | route | distance | weights | times | - | a,d | , | 59.9m | 20.5,0 | 24s,0s | - | a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s | - | d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s | + | a,d | , | 60m | 20.5,0 | 24s,0s | + | a,e | ,, | 60m | 27.2,10,0 | 38.5s,11s,0s | + | d,e | ,, | 40m | 10,10,0 | 11s,11s,0s | @traffic @speed Scenario: Step weights -- segment_function with speed and turn updates with fallback to durations @@ -375,10 +375,10 @@ Feature: Weight tests And the customize extra arguments "--segment-speed-file {speeds_file} --turn-penalty-file {penalties_file}" When I route I should get - | waypoints | route | distance | weights | times | - | a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s | - | a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s | - | d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s | + | waypoints | route | distance | weights | times | + | a,d | abcd,abcd | 60m | 7,0 | 7s,0s | + | a,e | abcd,ce,ce | 60m | 5.997,2.001,0 | 6s,2s,0s | + | d,e | abcd,ce,ce | 40m | 2.003,2.001,0 | 2s,2s,0s | @traffic @speed Scenario: Updating speeds without affecting weights. @@ -410,5 +410,5 @@ Feature: Weight tests And the customize extra arguments "--segment-speed-file {speeds_file}" When I route I should get - | waypoints | route | distance | weights | times | - | a,b | acdb,acdb | 78.3m | 11.744,0 | 56.4s,0s | + | waypoints | route | distance | weights | times | + | a,b | acdb,acdb | 78.3m | 11.742,0 | 56.4s,0s | diff --git a/include/engine/api/base_api.hpp b/include/engine/api/base_api.hpp index 6cd1a6e48..3f27dcf51 100644 --- a/include/engine/api/base_api.hpp +++ b/include/engine/api/base_api.hpp @@ -56,8 +56,8 @@ class BaseAPI // TODO: check forward/reverse return json::makeWaypoint( phantom.location, - util::coordinate_calculation::fccApproximateDistance(phantom.location, - phantom.input_location), + util::coordinate_calculation::greatCircleDistance(phantom.location, + phantom.input_location), facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(), Hint{phantom, facade.GetCheckSum()}); } @@ -66,8 +66,8 @@ class BaseAPI // TODO: check forward/reverse return json::makeWaypoint( phantom.location, - util::coordinate_calculation::fccApproximateDistance(phantom.location, - phantom.input_location), + util::coordinate_calculation::greatCircleDistance(phantom.location, + phantom.input_location), facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)) .to_string()); } @@ -114,7 +114,7 @@ class BaseAPI auto waypoint = std::make_unique(*builder); waypoint->add_location(&location); - waypoint->add_distance(util::coordinate_calculation::fccApproximateDistance( + waypoint->add_distance(util::coordinate_calculation::greatCircleDistance( phantom.location, phantom.input_location)); waypoint->add_name(name_string); if (parameters.generate_hints) diff --git a/include/engine/api/match_parameters_tidy.hpp b/include/engine/api/match_parameters_tidy.hpp index 198740afa..694dd6885 100644 --- a/include/engine/api/match_parameters_tidy.hpp +++ b/include/engine/api/match_parameters_tidy.hpp @@ -122,7 +122,7 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5}) // Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next) { - auto distance_delta = util::coordinate_calculation::haversineDistance( + auto distance_delta = util::coordinate_calculation::greatCircleDistance( params.coordinates[current], params.coordinates[next]); running.distance_in_meters += distance_delta; const auto over_distance = running.distance_in_meters >= cfg.distance_in_meters; diff --git a/include/engine/geospatial_query.hpp b/include/engine/geospatial_query.hpp index a8f4bb75f..2b01b20dd 100644 --- a/include/engine/geospatial_query.hpp +++ b/include/engine/geospatial_query.hpp @@ -484,7 +484,7 @@ template class GeospatialQuery current < forward_geometry.begin() + data.fwd_segment_position; ++current) { - forward_distance_offset += util::coordinate_calculation::fccApproximateDistance( + forward_distance_offset += util::coordinate_calculation::greatCircleDistance( datafacade.GetCoordinateOfNode(*current), datafacade.GetCoordinateOfNode(*std::next(current))); } @@ -494,7 +494,7 @@ template class GeospatialQuery EdgeWeight forward_weight = forward_weights[data.fwd_segment_position]; EdgeDuration forward_duration = forward_durations[data.fwd_segment_position]; - EdgeDistance forward_distance = util::coordinate_calculation::fccApproximateDistance( + EdgeDistance forward_distance = util::coordinate_calculation::greatCircleDistance( datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)), point_on_segment); @@ -514,7 +514,7 @@ template class GeospatialQuery current != std::prev(forward_geometry.end()); ++current) { - reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance( + reverse_distance_offset += util::coordinate_calculation::greatCircleDistance( datafacade.GetCoordinateOfNode(*current), datafacade.GetCoordinateOfNode(*std::next(current))); } @@ -523,7 +523,7 @@ template class GeospatialQuery reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1]; EdgeDuration reverse_duration = reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1]; - EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance( + EdgeDistance reverse_distance = util::coordinate_calculation::greatCircleDistance( point_on_segment, datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1))); @@ -592,8 +592,8 @@ template class GeospatialQuery Coordinate wsg84_coordinate = util::web_mercator::toWGS84(segment.fixed_projected_coordinate); - return util::coordinate_calculation::haversineDistance(input_coordinate, wsg84_coordinate) > - max_distance; + return util::coordinate_calculation::greatCircleDistance(input_coordinate, + wsg84_coordinate) > max_distance; } std::pair CheckSegmentExclude(const CandidateSegment &segment) const diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 9e3a0deaf..736c868fd 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -67,7 +67,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, { auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node); current_distance = - util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate); + util::coordinate_calculation::greatCircleDistance(prev_coordinate, coordinate); cumulative_distance += current_distance; // all changes to this check have to be matched with assemble_steps @@ -103,7 +103,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, } } current_distance = - util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location); + util::coordinate_calculation::greatCircleDistance(prev_coordinate, target_node.location); cumulative_distance += current_distance; // segment leading to the target node geometry.segment_distances.push_back(cumulative_distance); diff --git a/include/engine/plugins/plugin_base.hpp b/include/engine/plugins/plugin_base.hpp index abf344348..b437b1a6c 100644 --- a/include/engine/plugins/plugin_base.hpp +++ b/include/engine/plugins/plugin_base.hpp @@ -190,7 +190,7 @@ class BasePlugin { phantom_nodes[i].push_back(PhantomNodeWithDistance{ parameters.hints[i]->phantom, - util::coordinate_calculation::haversineDistance( + util::coordinate_calculation::greatCircleDistance( parameters.coordinates[i], parameters.hints[i]->phantom.location), }); continue; @@ -240,7 +240,7 @@ class BasePlugin { phantom_nodes[i].push_back(PhantomNodeWithDistance{ parameters.hints[i]->phantom, - util::coordinate_calculation::haversineDistance( + util::coordinate_calculation::greatCircleDistance( parameters.coordinates[i], parameters.hints[i]->phantom.location), }); continue; diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 70b7212fa..c7df59e80 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -428,7 +428,7 @@ template EdgeDistance computeEdgeDistance(const FacadeT &faca auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id); for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current) { - total_distance += util::coordinate_calculation::fccApproximateDistance( + total_distance += util::coordinate_calculation::greatCircleDistance( facade.GetCoordinateOfNode(*current), facade.GetCoordinateOfNode(*std::next(current))); } diff --git a/include/extractor/intersection/node_based_graph_walker.hpp b/include/extractor/intersection/node_based_graph_walker.hpp index 64f6a0b80..d076e5e43 100644 --- a/include/extractor/intersection/node_based_graph_walker.hpp +++ b/include/extractor/intersection/node_based_graph_walker.hpp @@ -301,7 +301,7 @@ struct DistanceToNextIntersectionAccumulator using namespace util::coordinate_calculation; const auto coords = extractor.GetForwardCoordinatesAlongRoad(start, onto); - distance += getLength(coords.begin(), coords.end(), &haversineDistance); + distance += getLength(coords.begin(), coords.end(), &greatCircleDistance); } const extractor::intersection::CoordinateExtractor &extractor; diff --git a/include/util/coordinate_calculation.hpp b/include/util/coordinate_calculation.hpp index 21719e26d..959a74107 100644 --- a/include/util/coordinate_calculation.hpp +++ b/include/util/coordinate_calculation.hpp @@ -43,11 +43,6 @@ inline double radToDeg(const double radian) //! Takes the squared euclidean distance of the input coordinates. Does not return meters! std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs); -double fccApproximateDistance(const Coordinate first_coordinate, - const Coordinate second_coordinate); - -double haversineDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); - double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); // get the length of a full coordinate vector, using one of our basic functions to compute distances diff --git a/package-lock.json b/package-lock.json index 96e98e2d9..58013b645 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "osrm", - "version": "5.26.0-unreleased", + "version": "5.27.0-unreleased", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3369,6 +3369,16 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bit-twiddle": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", @@ -3958,6 +3968,11 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "cheap-ruler": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz", + "integrity": "sha512-02T332h1/HTN6cDSufLP8x4JzDs2+VC+8qZ/N0kWIVPyc2xUkWwWh3B2fJxR7raXkL4Mq7k554mfuM9ofv/vGg==" + }, "chokidar": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", @@ -5284,6 +5299,7 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", "nan": "^2.12.1" } }, @@ -5695,6 +5711,7 @@ "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", "nan": "^2.12.1" } }, @@ -7220,6 +7237,13 @@ "object-assign": "^4.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", diff --git a/package.json b/package.json index c86aa1969..ccb56bf34 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.1", + "cheap-ruler": "^3.0.2", "mkdirp": "^0.5.5", "nan": "^2.14.2", "node-cmake": "^2.5.1", diff --git a/src/engine/guidance/assemble_steps.cpp b/src/engine/guidance/assemble_steps.cpp index 0184baf14..1e5b87a3f 100644 --- a/src/engine/guidance/assemble_steps.cpp +++ b/src/engine/guidance/assemble_steps.cpp @@ -25,7 +25,8 @@ std::pair getDepartBearings(const LegGeometry &leg_geometry, const auto turn_coordinate = leg_geometry.locations.front(); const auto post_turn_coordinate = *(leg_geometry.locations.begin() + 1); - if (util::coordinate_calculation::haversineDistance(turn_coordinate, post_turn_coordinate) <= 1) + if (util::coordinate_calculation::greatCircleDistance(turn_coordinate, post_turn_coordinate) <= + 1) { return std::make_pair(0, source_node.GetBearing(traversed_in_reverse)); } @@ -41,7 +42,8 @@ std::pair getArriveBearings(const LegGeometry &leg_geometry, BOOST_ASSERT(leg_geometry.locations.size() >= 2); const auto turn_coordinate = leg_geometry.locations.back(); const auto pre_turn_coordinate = *(leg_geometry.locations.end() - 2); - if (util::coordinate_calculation::haversineDistance(turn_coordinate, pre_turn_coordinate) <= 1) + if (util::coordinate_calculation::greatCircleDistance(turn_coordinate, pre_turn_coordinate) <= + 1) { return std::make_pair(target_node.GetBearing(traversed_in_reverse), 0); } diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index b5a280472..f510e04b0 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -263,7 +263,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) BOOST_ASSERT(geometry.locations.size() >= steps.size()); // Look for distances under 1m const bool zero_length_step = steps.front().distance <= 1 && steps.size() > 2; - const bool duplicated_coordinate = util::coordinate_calculation::haversineDistance( + const bool duplicated_coordinate = util::coordinate_calculation::greatCircleDistance( geometry.locations[0], geometry.locations[1]) <= 1; if (zero_length_step || duplicated_coordinate) { @@ -406,7 +406,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) next_to_last_step.mode = new_next_to_last.mode; // the geometry indices of the last step are already correct; } - else if (util::coordinate_calculation::haversineDistance( + else if (util::coordinate_calculation::greatCircleDistance( geometry.locations[geometry.locations.size() - 2], geometry.locations[geometry.locations.size() - 1]) <= 1) { @@ -463,7 +463,7 @@ std::vector assignRelativeLocations(std::vector steps, BOOST_ASSERT(steps.size() >= 2); BOOST_ASSERT(leg_geometry.locations.size() >= 2); const constexpr double MINIMAL_RELATIVE_DISTANCE = 5., MAXIMAL_RELATIVE_DISTANCE = 300.; - const auto distance_to_start = util::coordinate_calculation::haversineDistance( + const auto distance_to_start = util::coordinate_calculation::greatCircleDistance( source_node.input_location, leg_geometry.locations[0]); const auto initial_modifier = distance_to_start >= MINIMAL_RELATIVE_DISTANCE && @@ -474,7 +474,7 @@ std::vector assignRelativeLocations(std::vector steps, steps.front().maneuver.instruction.direction_modifier = initial_modifier; - const auto distance_from_end = util::coordinate_calculation::haversineDistance( + const auto distance_from_end = util::coordinate_calculation::greatCircleDistance( target_node.input_location, leg_geometry.locations.back()); const auto final_modifier = distance_from_end >= MINIMAL_RELATIVE_DISTANCE && diff --git a/src/engine/plugins/table.cpp b/src/engine/plugins/table.cpp index 82572f661..77760f71d 100644 --- a/src/engine/plugins/table.cpp +++ b/src/engine/plugins/table.cpp @@ -116,9 +116,9 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, auto distance_estimate = params.fallback_coordinate_type == api::TableParameters::FallbackCoordinateType::Input - ? util::coordinate_calculation::fccApproximateDistance( + ? util::coordinate_calculation::greatCircleDistance( source.input_location, destination.input_location) - : util::coordinate_calculation::fccApproximateDistance( + : util::coordinate_calculation::greatCircleDistance( source.location, destination.location); result_tables_pair.first[table_index] = diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index 511d6edaa..5a899edd4 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -464,7 +464,7 @@ void encodeVectorTile(const DataFacadeBase &facade, const auto b = facade.GetCoordinateOfNode(edge.v); // Calculate the length in meters const double length = - osrm::util::coordinate_calculation::haversineDistance(a, b); + osrm::util::coordinate_calculation::greatCircleDistance(a, b); const auto forward_weight_range = facade.GetUncompressedForwardWeights(geometry_id); diff --git a/src/engine/routing_algorithms/alternative_path_mld.cpp b/src/engine/routing_algorithms/alternative_path_mld.cpp index 51688c825..96329c27f 100644 --- a/src/engine/routing_algorithms/alternative_path_mld.cpp +++ b/src/engine/routing_algorithms/alternative_path_mld.cpp @@ -137,7 +137,7 @@ Parameters parametersFromRequest(const PhantomNodes &phantom_node_pair) { Parameters parameters; - const auto distance = util::coordinate_calculation::haversineDistance( + const auto distance = util::coordinate_calculation::greatCircleDistance( phantom_node_pair.source_phantom.location, phantom_node_pair.target_phantom.location); // 10km diff --git a/src/engine/routing_algorithms/map_matching.cpp b/src/engine/routing_algorithms/map_matching.cpp index 7b2bc053e..f5fbea093 100644 --- a/src/engine/routing_algorithms/map_matching.cpp +++ b/src/engine/routing_algorithms/map_matching.cpp @@ -214,7 +214,7 @@ SubMatchingList mapMatching(SearchEngineData &engine_working_data, const auto ¤t_timestamps_list = candidates_list[t]; const auto ¤t_coordinate = trace_coordinates[t]; - const auto haversine_distance = util::coordinate_calculation::haversineDistance( + const auto haversine_distance = util::coordinate_calculation::greatCircleDistance( prev_coordinate, current_coordinate); // assumes minumum of 4 m/s const EdgeWeight weight_upper_bound = @@ -424,7 +424,7 @@ SubMatchingList mapMatching(SearchEngineData &engine_working_data, reconstructed_indices, [&trace_distance, &trace_coordinates](const std::pair &prev, const std::pair &curr) { - trace_distance += util::coordinate_calculation::haversineDistance( + trace_distance += util::coordinate_calculation::greatCircleDistance( trace_coordinates[prev.first], trace_coordinates[curr.first]); }); diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp index a587c15c4..24d7b5e76 100644 --- a/src/extractor/extraction_containers.cpp +++ b/src/extractor/extraction_containers.cpp @@ -434,7 +434,7 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm const auto duration = edge_iterator->duration_data(distance); const auto accurate_distance = - util::coordinate_calculation::fccApproximateDistance(source_coord, target_coord); + util::coordinate_calculation::greatCircleDistance(source_coord, target_coord); ExtractionSegment segment(source_coord, target_coord, distance, weight, duration); scripting_environment.ProcessSegment(segment); diff --git a/src/extractor/intersection/coordinate_extractor.cpp b/src/extractor/intersection/coordinate_extractor.cpp index ed0d3dea6..18199a79d 100644 --- a/src/extractor/intersection/coordinate_extractor.cpp +++ b/src/extractor/intersection/coordinate_extractor.cpp @@ -146,12 +146,12 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate( // do the best of what we can. coordinates = TrimCoordinatesToLength(std::move(coordinates), LOOKAHEAD_DISTANCE_WITHOUT_LANES); - if (coordinates.size() > 2 && util::coordinate_calculation::haversineDistance( + if (coordinates.size() > 2 && util::coordinate_calculation::greatCircleDistance( turn_coordinate, coordinates[1]) < ASSUMED_LANE_WIDTH) { const auto initial_distance = - util::coordinate_calculation::haversineDistance(turn_coordinate, coordinates[1]); - const auto total_distance = util::coordinate_calculation::haversineDistance( + util::coordinate_calculation::greatCircleDistance(turn_coordinate, coordinates[1]); + const auto total_distance = util::coordinate_calculation::greatCircleDistance( turn_coordinate, coordinates.back()); if (initial_distance > ASSUMED_LANE_WIDTH && total_distance > initial_distance) @@ -169,7 +169,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate( } const auto first_distance = - util::coordinate_calculation::haversineDistance(coordinates[0], coordinates[1]); + util::coordinate_calculation::greatCircleDistance(coordinates[0], coordinates[1]); // the lane count might not always be set. We need to assume a positive number, though. Here we // select the number of lanes to operate on @@ -369,7 +369,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate( std::move(coordinates), 3 * skipping_inaccuracies_distance, segment_distances); BOOST_ASSERT(coordinates.size() >= 2); segment_distances.resize(coordinates.size()); - segment_distances.back() = util::coordinate_calculation::haversineDistance( + segment_distances.back() = util::coordinate_calculation::greatCircleDistance( *(coordinates.end() - 2), coordinates.back()); const auto vector_head = coordinates.back(); coordinates = TrimCoordinatesToLength( @@ -476,7 +476,7 @@ util::Coordinate CoordinateExtractor::ExtractCoordinateAtLength( [distance, &accumulated_distance, last_coordinate = coordinates.front()]( const util::Coordinate coordinate) mutable { const double segment_distance = - util::coordinate_calculation::haversineDistance(last_coordinate, coordinate); + util::coordinate_calculation::greatCircleDistance(last_coordinate, coordinate); const auto result = (accumulated_distance + segment_distance) >= distance; if (!result) { @@ -497,7 +497,7 @@ util::Coordinate CoordinateExtractor::ExtractCoordinateAtLength( const auto interpolation_factor = ComputeInterpolationFactor(distance - accumulated_distance, 0, - util::coordinate_calculation::haversineDistance( + util::coordinate_calculation::greatCircleDistance( *std::prev(coordinate_after), *coordinate_after)); return util::coordinate_calculation::interpolateLinear( @@ -533,7 +533,7 @@ util::Coordinate CoordinateExtractor::GetCoordinateCloseToTurn(const NodeID from const auto far_enough_away = [start_coordinate, compressedGeometryToCoordinate]( const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) { - return util::coordinate_calculation::haversineDistance( + return util::coordinate_calculation::greatCircleDistance( compressedGeometryToCoordinate(compressed_edge), start_coordinate) > 1; }; @@ -627,7 +627,7 @@ CoordinateExtractor::GetMaxDeviation(std::vector::const_iterat .second; // and calculate the distance between the intermediate coordinate and the coordinate // on the osrm-way - return util::coordinate_calculation::haversineDistance(coord_between, coordinate); + return util::coordinate_calculation::greatCircleDistance(coord_between, coordinate); }; // note: we don't accumulate here but rather compute the maximum. The functor passed here is not @@ -671,7 +671,7 @@ bool CoordinateExtractor::IsCurve(const std::vector &coordinat auto coord_between = util::coordinate_calculation::projectPointOnSegment(line_start, line_end, point).second; // and calculate the distance between the intermediate coordinate and the coordinate - return util::coordinate_calculation::haversineDistance(coord_between, point); + return util::coordinate_calculation::greatCircleDistance(coord_between, point); }; // a curve needs to be on one side of the coordinate array @@ -899,7 +899,7 @@ CoordinateExtractor::PrepareLengthCache(const std::vector &coo limit, &segment_distances, accumulated_distance = 0.](const util::Coordinate current_coordinate) mutable { - const auto distance = util::coordinate_calculation::haversineDistance( + const auto distance = util::coordinate_calculation::greatCircleDistance( last_coordinate, current_coordinate); accumulated_distance += distance; last_coordinate = current_coordinate; @@ -924,8 +924,8 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector coord [&coordinate_index, &distance_to_current_coordinate, &coordinates]() { const auto new_distance = distance_to_current_coordinate + - util::coordinate_calculation::haversineDistance(coordinates[coordinate_index - 1], - coordinates[coordinate_index]); + util::coordinate_calculation::greatCircleDistance(coordinates[coordinate_index - 1], + coordinates[coordinate_index]); return new_distance; }; @@ -941,8 +941,8 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector coord coordinates.erase(coordinates.begin() + length_cache.size(), coordinates.end()); const auto distance_between_last_coordinates = - util::coordinate_calculation::haversineDistance(*(coordinates.end() - 2), - *(coordinates.end() - 1)); + util::coordinate_calculation::greatCircleDistance(*(coordinates.end() - 2), + *(coordinates.end() - 1)); if (distance_between_last_coordinates > 0) { @@ -991,7 +991,7 @@ CoordinateExtractor::GetCorrectedCoordinate(const util::Coordinate fixpoint, { // if the coordinates are close together, we were not able to look far ahead, so // we can use the end-coordinate - if (util::coordinate_calculation::haversineDistance(vector_base, vector_head) < + if (util::coordinate_calculation::greatCircleDistance(vector_base, vector_head) < DESIRED_COORDINATE_DIFFERENCE) { return vector_head; @@ -1054,7 +1054,7 @@ CoordinateExtractor::SampleCoordinates(const std::vector &coor if (total_length > max_sample_length) return true; - const auto distance_between = util::coordinate_calculation::haversineDistance( + const auto distance_between = util::coordinate_calculation::greatCircleDistance( previous_coordinate, current_coordinate); if (carry_length + distance_between >= rate) @@ -1123,7 +1123,7 @@ CoordinateExtractor::TrimCoordinatesByLengthFront(std::vector for (std::size_t next_index = 1; next_index < coordinates.size(); ++next_index) { const double next_distance = - distance_to_index + util::coordinate_calculation::haversineDistance( + distance_to_index + util::coordinate_calculation::greatCircleDistance( coordinates[index], coordinates[next_index]); if (next_distance >= desired_length) { diff --git a/src/extractor/intersection/intersection_analysis.cpp b/src/extractor/intersection/intersection_analysis.cpp index d29d38d0a..542bbaafa 100644 --- a/src/extractor/intersection/intersection_analysis.cpp +++ b/src/extractor/intersection/intersection_analysis.cpp @@ -237,7 +237,7 @@ getIntersectionOutgoingGeometries(const util::NodeBasedDynamicGraph &graph, util::coordinate_calculation::bearing(geometry[0], representative_coordinate); const auto edge_length = util::coordinate_calculation::getLength( - geometry.begin(), geometry.end(), util::coordinate_calculation::haversineDistance); + geometry.begin(), geometry.end(), util::coordinate_calculation::greatCircleDistance); edge_geometries.push_back({outgoing_edge, initial_bearing, perceived_bearing, edge_length}); } diff --git a/src/extractor/intersection/mergable_road_detector.cpp b/src/extractor/intersection/mergable_road_detector.cpp index 29ebe25b0..a1c95054c 100644 --- a/src/extractor/intersection/mergable_road_detector.cpp +++ b/src/extractor/intersection/mergable_road_detector.cpp @@ -225,7 +225,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node, left_accumulator, selector); } - const auto distance_to_triangle = util::coordinate_calculation::haversineDistance( + const auto distance_to_triangle = util::coordinate_calculation::greatCircleDistance( node_coordinates[intersection_node], node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)]); @@ -274,9 +274,10 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node, // the width we can bridge at the intersection const auto assumed_road_width = (num_lanes(lhs) + num_lanes(rhs)) * ASSUMED_LANE_WIDTH; const constexpr auto MAXIMAL_ALLOWED_TRAFFIC_ISLAND_WIDTH = 10; - const auto distance_between_triangle_corners = util::coordinate_calculation::haversineDistance( - node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)], - node_coordinates[node_based_graph.GetTarget(right_accumulator.via_edge_id)]); + const auto distance_between_triangle_corners = + util::coordinate_calculation::greatCircleDistance( + node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)], + node_coordinates[node_based_graph.GetTarget(right_accumulator.via_edge_id)]); if (distance_between_triangle_corners > (assumed_road_width + MAXIMAL_ALLOWED_TRAFFIC_ISLAND_WIDTH)) return false; @@ -540,7 +541,7 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node, if (!degree_three_connect_in && !degree_three_connect_out) return false; - const auto distance_between_candidates = util::coordinate_calculation::haversineDistance( + const auto distance_between_candidates = util::coordinate_calculation::greatCircleDistance( node_coordinates[intersection_node], node_coordinates[left_candidate]); const auto both_split_join = degree_three_connect_in && degree_three_connect_out; diff --git a/src/extractor/intersection/node_based_graph_walker.cpp b/src/extractor/intersection/node_based_graph_walker.cpp index a8b6401bd..308a467b2 100644 --- a/src/extractor/intersection/node_based_graph_walker.cpp +++ b/src/extractor/intersection/node_based_graph_walker.cpp @@ -50,7 +50,7 @@ void LengthLimitedCoordinateAccumulator::update(const NodeID from_node, const auto length = util::coordinate_calculation::getLength(current_coordinates.begin(), current_coordinates.end(), - util::coordinate_calculation::haversineDistance); + util::coordinate_calculation::greatCircleDistance); // in case we get too many coordinates, we limit them to our desired length if (length + accumulated_length > max_length) diff --git a/src/guidance/intersection_handler.cpp b/src/guidance/intersection_handler.cpp index 0dedc8f9a..c2142bacc 100644 --- a/src/guidance/intersection_handler.cpp +++ b/src/guidance/intersection_handler.cpp @@ -183,7 +183,7 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t // duration/weight of the traversal. We can only approximate the distance here // or actually follow the full road. When 2399 lands, we can exchange here for a // precalculated distance value. - const auto distance = util::coordinate_calculation::haversineDistance( + const auto distance = util::coordinate_calculation::greatCircleDistance( node_coordinates[node_based_graph.GetTarget(via_edge)], node_coordinates[node_based_graph.GetTarget(road.eid)]); diff --git a/src/guidance/roundabout_handler.cpp b/src/guidance/roundabout_handler.cpp index 90b813988..8e9f9f0b4 100644 --- a/src/guidance/roundabout_handler.cpp +++ b/src/guidance/roundabout_handler.cpp @@ -274,7 +274,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const for (const auto &compressed_edge : edge_bucket) { const auto next_coord = node_coordinates[compressed_edge.node_id]; - length += util::coordinate_calculation::haversineDistance(last_coord, next_coord); + length += util::coordinate_calculation::greatCircleDistance(last_coord, next_coord); last_coord = next_coord; } return length; diff --git a/src/guidance/segregated_intersection_classification.cpp b/src/guidance/segregated_intersection_classification.cpp index 6ff608d91..e0d60381c 100644 --- a/src/guidance/segregated_intersection_classification.cpp +++ b/src/guidance/segregated_intersection_classification.cpp @@ -56,7 +56,7 @@ std::unordered_set findSegregatedNodes(const extractor::NodeBasedGraphFa double length = 0.0; for (size_t i = 1; i < geom.size(); ++i) { - length += util::coordinate_calculation::haversineDistance(geom[i - 1], geom[i]); + length += util::coordinate_calculation::greatCircleDistance(geom[i - 1], geom[i]); } return length; }; diff --git a/src/guidance/sliproad_handler.cpp b/src/guidance/sliproad_handler.cpp index a7992322a..569cb6405 100644 --- a/src/guidance/sliproad_handler.cpp +++ b/src/guidance/sliproad_handler.cpp @@ -452,8 +452,8 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/, // Only check for curvature and ~90 degree when it makes sense to do so. const constexpr auto MIN_LENGTH = 3.; - const auto length = haversineDistance(node_coordinates[intersection_node_id], - node_coordinates[main_road_intersection->node]); + const auto length = greatCircleDistance(node_coordinates[intersection_node_id], + node_coordinates[main_road_intersection->node]); const double minimal_crossroad_angle_of_intersection = 40.; @@ -740,8 +740,8 @@ bool SliproadHandler::isValidSliproadArea(const double max_area, const auto second = node_coordinates[b]; const auto third = node_coordinates[c]; - const auto length = haversineDistance(first, second); - const auto heigth = haversineDistance(second, third); + const auto length = greatCircleDistance(first, second); + const auto heigth = greatCircleDistance(second, third); const auto area = (length * heigth) / 2.; diff --git a/src/guidance/turn_discovery.cpp b/src/guidance/turn_discovery.cpp index cdfffd4b4..d5138ecf1 100644 --- a/src/guidance/turn_discovery.cpp +++ b/src/guidance/turn_discovery.cpp @@ -51,7 +51,7 @@ bool findPreviousIntersection(const NodeID node_v, const auto via_edge_length = util::coordinate_calculation::getLength(coordinates_along_via_edge.begin(), coordinates_along_via_edge.end(), - &util::coordinate_calculation::haversineDistance); + &util::coordinate_calculation::greatCircleDistance); // we check if via-edge is too short. In this case the previous turn cannot influence the turn // at via_edge and the intersection at NODE_W diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index 4aa544b02..bdc4d1206 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -72,12 +72,10 @@ std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rh return result; } -// Uses method described here: -// https://www.gpo.gov/fdsys/pkg/CFR-2005-title47-vol4/pdf/CFR-2005-title47-vol4-sec73-208.pdf -// should be within 0.1% or so of Vincenty method (assuming 19 buckets are enough) -// Should be more faster and more precise than Haversine -double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) +double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) { + // Should be within 0.1% or so of Vincenty method (assuming 19 buckets are enough) + // Should be more faster and more precise than Haversine const auto lon1 = static_cast(util::toFloating(coordinate_1.lon)); const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); @@ -86,56 +84,6 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co .distance({lon1, lat1}, {lon2, lat2}); } -double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) -{ - auto lon1 = static_cast(coordinate_1.lon); - auto lat1 = static_cast(coordinate_1.lat); - auto lon2 = static_cast(coordinate_2.lon); - auto lat2 = static_cast(coordinate_2.lat); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - const double lt1 = lat1 / COORDINATE_PRECISION; - const double ln1 = lon1 / COORDINATE_PRECISION; - const double lt2 = lat2 / COORDINATE_PRECISION; - const double ln2 = lon2 / COORDINATE_PRECISION; - - const double dlat1 = lt1 * detail::DEGREE_TO_RAD; - const double dlong1 = ln1 * detail::DEGREE_TO_RAD; - const double dlat2 = lt2 * detail::DEGREE_TO_RAD; - const double dlong2 = ln2 * detail::DEGREE_TO_RAD; - - const double dlong = dlong1 - dlong2; - const double dlat = dlat1 - dlat2; - - const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) + - std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2); - const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv)); - return detail::EARTH_RADIUS * charv; -} - -double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) -{ - auto lon1 = static_cast(coordinate_1.lon); - auto lat1 = static_cast(coordinate_1.lat); - auto lon2 = static_cast(coordinate_2.lon); - auto lat2 = static_cast(coordinate_2.lat); - BOOST_ASSERT(lat1 != std::numeric_limits::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::min()); - - const double float_lat1 = (lat1 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD; - const double float_lon1 = (lon1 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD; - const double float_lat2 = (lat2 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD; - const double float_lon2 = (lon2 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD; - - const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0); - const double y_value = float_lat2 - float_lat1; - return std::hypot(x_value, y_value) * detail::EARTH_RADIUS; -} - double perpendicularDistance(const Coordinate segment_source, const Coordinate segment_target, const Coordinate query_location, @@ -153,7 +101,7 @@ double perpendicularDistance(const Coordinate segment_source, web_mercator::fromWGS84(query_location)); nearest_location = web_mercator::toWGS84(projected_nearest); - const double approximate_distance = fccApproximateDistance(query_location, nearest_location); + const double approximate_distance = greatCircleDistance(query_location, nearest_location); BOOST_ASSERT(0.0 <= approximate_distance); return approximate_distance; } @@ -179,30 +127,24 @@ Coordinate centroid(const Coordinate lhs, const Coordinate rhs) return centroid; } -double bearing(const Coordinate first_coordinate, const Coordinate second_coordinate) +double bearing(const Coordinate coordinate_1, const Coordinate coordinate_2) { - const double lon_diff = - static_cast(toFloating(second_coordinate.lon - first_coordinate.lon)); - const double lon_delta = detail::degToRad(lon_diff); - const double lat1 = detail::degToRad(static_cast(toFloating(first_coordinate.lat))); - const double lat2 = detail::degToRad(static_cast(toFloating(second_coordinate.lat))); - const double y = std::sin(lon_delta) * std::cos(lat2); - const double x = - std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta); - double result = detail::radToDeg(std::atan2(y, x)); - while (result < 0.0) + const auto lon1 = static_cast(util::toFloating(coordinate_1.lon)); + const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); + const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); + const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); + const auto &ruler = cheap_ruler_container.getRuler(coordinate_1.lat, coordinate_2.lat); + auto result = ruler.bearing({lon1, lat1}, {lon2, lat2}); + if (result < 0.0) { result += 360.0; } + BOOST_ASSERT(0 <= result && result <= 360); - while (result >= 360.0) - { - result -= 360.0; - } // If someone gives us two identical coordinates, then the concept of a bearing // makes no sense. However, because it sometimes happens, we'll at least // return a consistent value of 0 so that the behaviour isn't random. - BOOST_ASSERT(first_coordinate != second_coordinate || result == 0.); + BOOST_ASSERT(coordinate_1 != coordinate_2 || result == 0.); return result; } @@ -322,7 +264,7 @@ double circleRadius(const Coordinate C1, const Coordinate C2, const Coordinate C // a circle by three points requires thee distinct points auto center = circleCenter(C1, C2, C3); if (center) - return haversineDistance(C1, *center); + return greatCircleDistance(C1, *center); else return std::numeric_limits::infinity(); } @@ -372,8 +314,8 @@ double findClosestDistance(const Coordinate coordinate, const Coordinate segment_begin, const Coordinate segment_end) { - return haversineDistance(coordinate, - projectPointOnSegment(segment_begin, segment_end, coordinate).second); + return greatCircleDistance( + coordinate, projectPointOnSegment(segment_begin, segment_end, coordinate).second); } // find the closes distance between two sets of coordinates @@ -437,7 +379,7 @@ Coordinate difference(const Coordinate lhs, const Coordinate rhs) double computeArea(const std::vector &polygon) { - using util::coordinate_calculation::haversineDistance; + using util::coordinate_calculation::greatCircleDistance; if (polygon.empty()) return 0.; @@ -458,15 +400,15 @@ double computeArea(const std::vector &polygon) double area = 0.; auto first = polygon.begin(); auto previous_base = util::Coordinate{first->lon, ref_latitude}; - auto previous_y = haversineDistance(previous_base, *first); + auto previous_y = greatCircleDistance(previous_base, *first); for (++first; first != polygon.end(); ++first) { BOOST_ASSERT(first->lat >= ref_latitude); const auto current_base = util::Coordinate{first->lon, ref_latitude}; - const auto current_y = haversineDistance(current_base, *first); + const auto current_y = greatCircleDistance(current_base, *first); const auto chunk_area = - haversineDistance(previous_base, current_base) * (previous_y + current_y); + greatCircleDistance(previous_base, current_base) * (previous_y + current_y); area += (current_base.lon >= previous_base.lon) ? chunk_area : -chunk_area; diff --git a/test/nodejs/constants.js b/test/nodejs/constants.js index a6a32ca25..72b93da30 100644 --- a/test/nodejs/constants.js +++ b/test/nodejs/constants.js @@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956], exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2) -exports.test_tile = {'at': [17059, 11948, 15], 'size': 156624}; +exports.test_tile = {'at': [17059, 11948, 15], 'size': 156539}; // Test files generated by the routing engine; check test/data if (process.env.OSRM_DATA_PATH !== undefined) { diff --git a/test/nodejs/route.js b/test/nodejs/route.js index f23eaf3ee..7d27639ea 100644 --- a/test/nodejs/route.js +++ b/test/nodejs/route.js @@ -708,6 +708,6 @@ test('route: snapping parameter passed through OK', function(assert) { var osrm = new OSRM(monaco_path); osrm.route({snapping: "any", coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]]}, function(err, route) { assert.ifError(err); - assert.equal(Math.round(route.routes[0].distance * 10), 1314); // Round it to nearest 0.1m to eliminate floating point comparison error + assert.equal(Math.round(route.routes[0].distance * 10), 1315); // Round it to nearest 0.1m to eliminate floating point comparison error }); }); \ No newline at end of file diff --git a/third_party/cheap-ruler-cpp-2.5.4/.clang-format b/third_party/cheap-ruler-cpp-2778eb8/.clang-format similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/.clang-format rename to third_party/cheap-ruler-cpp-2778eb8/.clang-format diff --git a/third_party/cheap-ruler-cpp-2.5.4/.gitignore b/third_party/cheap-ruler-cpp-2778eb8/.gitignore similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/.gitignore rename to third_party/cheap-ruler-cpp-2778eb8/.gitignore diff --git a/third_party/cheap-ruler-cpp-2.5.4/.travis.yml b/third_party/cheap-ruler-cpp-2778eb8/.travis.yml similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/.travis.yml rename to third_party/cheap-ruler-cpp-2778eb8/.travis.yml diff --git a/third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt b/third_party/cheap-ruler-cpp-2778eb8/CMakeLists.txt similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt rename to third_party/cheap-ruler-cpp-2778eb8/CMakeLists.txt diff --git a/third_party/cheap-ruler-cpp-2.5.4/LICENSE b/third_party/cheap-ruler-cpp-2778eb8/LICENSE similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/LICENSE rename to third_party/cheap-ruler-cpp-2778eb8/LICENSE diff --git a/third_party/cheap-ruler-cpp-2.5.4/README.md b/third_party/cheap-ruler-cpp-2778eb8/README.md similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/README.md rename to third_party/cheap-ruler-cpp-2778eb8/README.md diff --git a/third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake b/third_party/cheap-ruler-cpp-2778eb8/cmake/build.cmake similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake rename to third_party/cheap-ruler-cpp-2778eb8/cmake/build.cmake diff --git a/third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake b/third_party/cheap-ruler-cpp-2778eb8/cmake/mason.cmake similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake rename to third_party/cheap-ruler-cpp-2778eb8/cmake/mason.cmake diff --git a/third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp b/third_party/cheap-ruler-cpp-2778eb8/include/mapbox/cheap_ruler.hpp similarity index 67% rename from third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp rename to third_party/cheap-ruler-cpp-2778eb8/include/mapbox/cheap_ruler.hpp index d5ae7428b..19854fc08 100644 --- a/third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp +++ b/third_party/cheap-ruler-cpp-2778eb8/include/mapbox/cheap_ruler.hpp @@ -1,7 +1,10 @@ #pragma once -#include +#include +#include +#include +#include #include #include #include @@ -19,6 +22,14 @@ using point = geometry::point; using polygon = geometry::polygon; class CheapRuler { + + // Values that define WGS84 ellipsoid model of the Earth + static constexpr double RE = 6378.137; // equatorial radius + static constexpr double FE = 1.0 / 298.257223563; // flattening + + static constexpr double E2 = FE * (2 - FE); + static constexpr double RAD = M_PI / 180.0; + public: enum Unit { Kilometers, @@ -63,68 +74,61 @@ public: break; } - auto cos = std::cos(latitude * M_PI / 180.); - auto cos2 = 2. * cos * cos - 1.; - auto cos3 = 2. * cos * cos2 - cos; - auto cos4 = 2. * cos * cos3 - cos2; - auto cos5 = 2. * cos * cos4 - cos3; + // Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional + double mul = RAD * RE * m; + double coslat = std::cos(latitude * RAD); + double w2 = 1 / (1 - E2 * (1 - coslat * coslat)); + double w = std::sqrt(w2); - // multipliers for converting longitude and latitude - // degrees into distance (http://1.usa.gov/1Wb1bv7) - kx = m * (111.41513 * cos - 0.09455 * cos3 + 0.00012 * cos5); - ky = m * (111.13209 - 0.56605 * cos2 + 0.0012 * cos4); + // multipliers for converting longitude and latitude degrees into distance + kx = mul * w * coslat; // based on normal radius of curvature + ky = mul * w * w2 * (1 - E2); // based on meridonal radius of curvature } static CheapRuler fromTile(uint32_t y, uint32_t z) { - double n = M_PI * (1. - 2. * (y + 0.5) / std::pow(2., z)); - double latitude = std::atan(0.5 * (std::exp(n) - std::exp(-n))) * 180. / M_PI; + assert(z < 32); + double n = M_PI * (1. - 2. * (y + 0.5) / double(uint32_t(1) << z)); + double latitude = std::atan(std::sinh(n)) / RAD; return CheapRuler(latitude); } + double squareDistance(point a, point b) const { + auto dx = longDiff(a.x, b.x) * kx; + auto dy = (a.y - b.y) * ky; + return dx * dx + dy * dy; + } + // // Given two points of the form [x = longitude, y = latitude], returns the distance. // - double distance(point a, point b) { - auto dx = (a.x - b.x) * kx; - auto dy = (a.y - b.y) * ky; - - return std::sqrt(dx * dx + dy * dy); + double distance(point a, point b) const { + return std::sqrt(squareDistance(a, b)); } // // Returns the bearing between two points in angles. // - double bearing(point a, point b) { - auto dx = (b.x - a.x) * kx; + double bearing(point a, point b) const { + auto dx = longDiff(b.x, a.x) * kx; auto dy = (b.y - a.y) * ky; - if (!dx && !dy) { - return 0.; - } - - auto value = std::atan2(dx, dy) * 180. / M_PI; - - if (value > 180.) { - value -= 360.; - } - - return value; + return std::atan2(dx, dy) / RAD; } // // Returns a new point given distance and bearing from the starting point. // - point destination(point origin, double dist, double bearing_) { - auto a = (90. - bearing_) * M_PI / 180.; + point destination(point origin, double dist, double bearing_) const { + auto a = bearing_ * RAD; - return offset(origin, std::cos(a) * dist, std::sin(a) * dist); + return offset(origin, std::sin(a) * dist, std::cos(a) * dist); } // // Returns a new point given easting and northing offsets from the starting point. // - point offset(point origin, double dx, double dy) { + point offset(point origin, double dx, double dy) const { return point(origin.x + dx / kx, origin.y + dy / ky); } @@ -134,8 +138,8 @@ public: double lineDistance(const line_string& points) { double total = 0.; - for (unsigned i = 0; i < points.size() - 1; ++i) { - total += distance(points[i], points[i + 1]); + for (size_t i = 1; i < points.size(); ++i) { + total += distance(points[i - 1], points[i]); } return total; @@ -145,14 +149,15 @@ public: // Given a polygon (an array of rings, where each ring is an array of points), // returns the area. // - double area(polygon poly) { + double area(polygon poly) const { double sum = 0.; for (unsigned i = 0; i < poly.size(); ++i) { auto& ring = poly[i]; for (unsigned j = 0, len = ring.size(), k = len - 1; j < len; k = j++) { - sum += (ring[j].x - ring[k].x) * (ring[j].y + ring[k].y) * (i ? -1. : 1.); + sum += longDiff(ring[j].x, ring[k].x) * + (ring[j].y + ring[k].y) * (i ? -1. : 1.); } } @@ -162,9 +167,13 @@ public: // // Returns the point at a specified distance along the line. // - point along(const line_string& line, double dist) { + point along(const line_string& line, double dist) const { double sum = 0.; + if (line.empty()) { + return {}; + } + if (dist <= 0.) { return line[0]; } @@ -184,25 +193,52 @@ public: return line[line.size() - 1]; } + // + // Returns the distance from a point `p` to a line segment `a` to `b`. + // + double pointToSegmentDistance(const point& p, const point& a, const point& b) const { + auto t = 0.0; + auto x = a.x; + auto y = a.y; + auto dx = longDiff(b.x, x) * kx; + auto dy = (b.y - y) * ky; + + if (dx != 0.0 || dy != 0.0) { + t = (longDiff(p.x, x) * kx * dx + (p.y - y) * ky * dy) / (dx * dx + dy * dy); + if (t > 1.0) { + x = b.x; + y = b.y; + } else if (t > 0.0) { + x += (dx / kx) * t; + y += (dy / ky) * t; + } + } + return distance(p, { x, y }); + } + // // Returns a tuple of the form where point is closest point on the line // from the given point, index is the start index of the segment with the closest point, // and t is a parameter from 0 to 1 that indicates where the closest point is on that segment. // - std::tuple pointOnLine(const line_string& line, point p) { + std::tuple pointOnLine(const line_string& line, point p) const { double minDist = std::numeric_limits::infinity(); double minX = 0., minY = 0., minI = 0., minT = 0.; + if (line.empty()) { + return std::make_tuple(point(), 0., 0.); + } + for (unsigned i = 0; i < line.size() - 1; ++i) { auto t = 0.; auto x = line[i].x; auto y = line[i].y; - auto dx = (line[i + 1].x - x) * kx; + auto dx = longDiff(line[i + 1].x, x) * kx; auto dy = (line[i + 1].y - y) * ky; if (dx != 0. || dy != 0.) { - t = ((p.x - x) * kx * dx + (p.y - y) * ky * dy) / (dx * dx + dy * dy); - + t = (longDiff(p.x, x) * kx * dx + + (p.y - y) * ky * dy) / (dx * dx + dy * dy); if (t > 1) { x = line[i + 1].x; y = line[i + 1].y; @@ -213,10 +249,7 @@ public: } } - dx = (p.x - x) * kx; - dy = (p.y - y) * ky; - - auto sqDist = dx * dx + dy * dy; + auto sqDist = squareDistance(p, {x, y}); if (sqDist < minDist) { minDist = sqDist; @@ -235,7 +268,7 @@ public: // Returns a part of the given line between the start and the stop points (or their closest // points on the line). // - line_string lineSlice(point start, point stop, const line_string& line) { + line_string lineSlice(point start, point stop, const line_string& line) const { auto getPoint = [](auto tuple) { return std::get<0>(tuple); }; auto getIndex = [](auto tuple) { return std::get<1>(tuple); }; auto getT = [](auto tuple) { return std::get<2>(tuple); }; @@ -273,13 +306,13 @@ public: // Returns a part of the given line between the start and the stop points // indicated by distance along the line. // - line_string lineSliceAlong(double start, double stop, const line_string& line) { + line_string lineSliceAlong(double start, double stop, const line_string& line) const { double sum = 0.; line_string slice; - for (unsigned i = 0; i < line.size() - 1; ++i) { - auto p0 = line[i]; - auto p1 = line[i + 1]; + for (size_t i = 1; i < line.size(); ++i) { + auto p0 = line[i - 1]; + auto p1 = line[i]; auto d = distance(p0, p1); sum += d; @@ -305,7 +338,7 @@ public: // Given a point, returns a bounding box object ([w, s, e, n]) // created from the given point buffered by a given distance. // - box bufferPoint(point p, double buffer) { + box bufferPoint(point p, double buffer) const { auto v = buffer / ky; auto h = buffer / kx; @@ -318,7 +351,7 @@ public: // // Given a bounding box, returns the box buffered by a given distance. // - box bufferBBox(box bbox, double buffer) { + box bufferBBox(box bbox, double buffer) const { auto v = buffer / ky; auto h = buffer / kx; @@ -331,15 +364,15 @@ public: // // Returns true if the given point is inside in the given bounding box, otherwise false. // - bool insideBBox(point p, box bbox) { - return p.x >= bbox.min.x && - p.x <= bbox.max.x && - p.y >= bbox.min.y && - p.y <= bbox.max.y; + static bool insideBBox(point p, box bbox) { + return p.y >= bbox.min.y && + p.y <= bbox.max.y && + longDiff(p.x, bbox.min.x) >= 0 && + longDiff(p.x, bbox.max.x) <= 0; } static point interpolate(point a, point b, double t) { - double dx = b.x - a.x; + double dx = longDiff(b.x, a.x); double dy = b.y - a.y; return point(a.x + dx * t, a.y + dy * t); @@ -348,6 +381,9 @@ public: private: double ky; double kx; + static double longDiff(double a, double b) { + return std::remainder(a - b, 360); + } }; } // namespace cheap_ruler diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp b/third_party/cheap-ruler-cpp-2778eb8/test/cheap_ruler.cpp similarity index 65% rename from third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp rename to third_party/cheap-ruler-cpp-2778eb8/test/cheap_ruler.cpp index 0ac73c81f..bd51f7ee8 100644 --- a/third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp +++ b/third_party/cheap-ruler-cpp-2778eb8/test/cheap_ruler.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "fixtures/lines.hpp" #include "fixtures/turf.hpp" @@ -60,6 +61,13 @@ TEST_F(CheapRulerTest, destination) { } TEST_F(CheapRulerTest, lineDistance) { + { + cr::line_string emptyLine {}; + auto expected = 0.0; + auto actual = ruler.lineDistance(emptyLine); + assertErr(expected, actual, 0.0); + } + for (unsigned i = 0; i < lines.size(); ++i) { auto expected = turf_lineDistance[i]; auto actual = ruler.lineDistance(lines[i]); @@ -88,6 +96,16 @@ TEST_F(CheapRulerTest, area) { } TEST_F(CheapRulerTest, along) { + { + cr::point emptyPoint {}; + cr::line_string emptyLine {}; + auto expected = emptyPoint; + auto actual = ruler.along(emptyLine, 0.0); + + assertErr(expected.x, actual.x, 0.0); + assertErr(expected.y, actual.y, 0.0); + } + for (unsigned i = 0; i < lines.size(); ++i) { auto expected = turf_along[i]; auto actual = ruler.along(lines[i], turf_along_dist[i]); @@ -110,14 +128,23 @@ TEST_F(CheapRulerTest, pointOnLine) { cr::line_string line = {{ -77.031669, 38.878605 }, { -77.029609, 38.881946 }}; auto result = ruler.pointOnLine(line, { -77.034076, 38.882017 }); - ASSERT_EQ(std::get<0>(result), cr::point(-77.03052697027461, 38.880457194811896)); // point + assertErr(std::get<0>(result).x, -77.03052689033436, 1e-6); + assertErr(std::get<0>(result).y, 38.880457324462576, 1e-6); ASSERT_EQ(std::get<1>(result), 0u); // index - ASSERT_EQ(std::get<2>(result), 0.5543833618360235); // t + assertErr(std::get<2>(result), 0.5544221677861756, 1e-6); // t ASSERT_EQ(std::get<2>(ruler.pointOnLine(line, { -80., 38. })), 0.) << "t is not less than 0"; ASSERT_EQ(std::get<2>(ruler.pointOnLine(line, { -75., 38. })), 1.) << "t is not bigger than 1"; } +TEST_F(CheapRulerTest, pointToSegmentDistance) { + cr::point p{ -77.034076, 38.882017 }; + cr::point p0{ -77.031669, 38.878605 }; + cr::point p1{ -77.029609, 38.881946 }; + const auto distance = ruler.pointToSegmentDistance(p, p0, p1); + assertErr(0.37461484020420416, distance, 1e-6); +} + TEST_F(CheapRulerTest, lineSlice) { for (unsigned i = 0; i < lines.size(); ++i) { auto line = lines[i]; @@ -127,11 +154,19 @@ TEST_F(CheapRulerTest, lineSlice) { auto expected = turf_lineSlice[i]; auto actual = ruler.lineDistance(ruler.lineSlice(start, stop, line)); - assertErr(expected, actual, 1e-5); + /// @todo Should update turf_lineSlice and revert maxError back. + assertErr(expected, actual, 1e-4); } } TEST_F(CheapRulerTest, lineSliceAlong) { + { + cr::line_string emptyLine {}; + auto expected = ruler.lineDistance(emptyLine); + auto actual = ruler.lineDistance(ruler.lineSliceAlong(0.0, 0.0, emptyLine)); + assertErr(expected, actual, 0.0); + } + for (unsigned i = 0; i < lines.size(); ++i) { if (i == 46) { // skip due to Turf bug https://github.com/Turfjs/turf/issues/351 @@ -143,7 +178,8 @@ TEST_F(CheapRulerTest, lineSliceAlong) { auto expected = turf_lineSlice[i]; auto actual = ruler.lineDistance(ruler.lineSliceAlong(dist * 0.3, dist * 0.7, line)); - assertErr(expected, actual, 1e-5); + /// @todo Should update turf_lineSlice and revert maxError back. + assertErr(expected, actual, 1e-4); } } @@ -154,7 +190,7 @@ TEST_F(CheapRulerTest, lineSliceReverse) { auto stop = ruler.along(line, dist * 0.3); auto actual = ruler.lineDistance(ruler.lineSlice(start, stop, line)); - ASSERT_EQ(actual, 0.018676802802910702); + assertErr(0.018676476689649835, actual, 1e-6); } TEST_F(CheapRulerTest, bufferPoint) { @@ -173,7 +209,10 @@ TEST_F(CheapRulerTest, bufferBBox) { cr::box bbox({ 30, 38 }, { 40, 39 }); cr::box bbox2 = ruler.bufferBBox(bbox, 1); - ASSERT_EQ(bbox2, cr::box({ 29.989319515875376, 37.99098271225711 }, { 40.01068048412462, 39.00901728774289 })); + assertErr(bbox2.min.x, 29.989319515875376, 1e-6); + assertErr(bbox2.min.y, 37.99098271225711, 1e-6); + assertErr(bbox2.max.x, 40.01068048412462, 1e-6); + assertErr(bbox2.max.y, 39.00901728774289, 1e-6); } TEST_F(CheapRulerTest, insideBBox) { @@ -193,6 +232,43 @@ TEST_F(CheapRulerTest, fromTile) { assertErr(ruler1.distance(p1, p2), ruler2.distance(p1, p2), 2e-5); } +TEST_F(CheapRulerTest, longitudeWrap) { + std::random_device rd; + std::mt19937 gen(rd()); + std::bernoulli_distribution d(0.5); // true with prob 0.5 + + auto r = cr::CheapRuler(50.5); + cr::polygon poly(1); + auto& ring = poly[0]; + cr::line_string line; + cr::point origin(0, 50.5); // Greenwich + auto rad = 1000.0; + // construct a regular dodecagon + for (int i = -180; i <= 180; i += 30) { + auto p = r.destination(origin, rad, i); + // shift randomly east/west to the international date line + p.x += d(gen) ? 180 : -180; + ring.push_back(p); + line.push_back(p); + } + auto p = r.lineDistance(line); + auto a = r.area(poly); + // cheap_ruler does planar calculations, so the perimeter and area of a + // planar regular dodecagon with circumradius rad are used in these checks. + // For the record, the results for rad = 1000 km are: + // perimeter area + // planar 6211.657082 3000000 + // WGS84 6187.959236 2996317.6328 + // error 0.38% 0.12% + assertErr(12 * rad / sqrt(2 + sqrt(3.0)), p, 1e-12); + assertErr(3 * rad * rad, a, 1e-12); + for (int j = 1; j < (int)line.size(); ++j) { + auto azi = r.bearing(line[j-1], line[j]); + // offset expect and actual by 1 to make err criterion absolute + assertErr(1, std::remainder(270 - 15 + 30*j - azi, 360) + 1, 1e-12); + } +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp b/third_party/cheap-ruler-cpp-2778eb8/test/fixtures/lines.hpp similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp rename to third_party/cheap-ruler-cpp-2778eb8/test/fixtures/lines.hpp diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp b/third_party/cheap-ruler-cpp-2778eb8/test/fixtures/turf.hpp similarity index 100% rename from third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp rename to third_party/cheap-ruler-cpp-2778eb8/test/fixtures/turf.hpp diff --git a/unit_tests/library/tile.cpp b/unit_tests/library/tile.cpp index 9bfe7bade..00a6c3846 100644 --- a/unit_tests/library/tile.cpp +++ b/unit_tests/library/tile.cpp @@ -90,7 +90,7 @@ void validate_feature_layer(vtzero::layer layer) std::count_if(layer.value_table().begin(), layer.value_table().end(), [](auto v) { return v.type() == vtzero::property_value_type::uint_value; }); - BOOST_CHECK_EQUAL(number_of_uint_values, 78); + BOOST_CHECK_EQUAL(number_of_uint_values, 79); } void validate_turn_layer(vtzero::layer layer) @@ -133,7 +133,7 @@ void validate_turn_layer(vtzero::layer layer) return v.type() == vtzero::property_value_type::float_value; }); - BOOST_CHECK_EQUAL(number_of_float_values, 74); + BOOST_CHECK_EQUAL(number_of_float_values, 73); } void validate_node_layer(vtzero::layer layer) @@ -322,13 +322,13 @@ void test_tile_turns(const osrm::OSRM &osrm, bool use_string_only_api) // Verify the expected turn angles std::sort(actual_turn_angles.begin(), actual_turn_angles.end()); const std::vector expected_turn_angles = { - -122, -120, -117, -65, -57, -30, -28, -3, -2, 2, 3, 28, 30, 57, 65, 117, 120, 122}; + -122, -120, -117, -65, -58, -30, -28, -2, -2, 2, 2, 28, 30, 58, 65, 117, 120, 122}; CHECK_EQUAL_RANGE(actual_turn_angles, expected_turn_angles); // Verify the expected bearings std::sort(actual_turn_bearings.begin(), actual_turn_bearings.end()); const std::vector expected_turn_bearings = { - 49, 49, 107, 107, 169, 169, 171, 171, 229, 229, 257, 257, 286, 286, 349, 349, 352, 352}; + 49, 49, 107, 107, 169, 169, 171, 171, 229, 229, 257, 257, 286, 286, 349, 349, 351, 351}; CHECK_EQUAL_RANGE(actual_turn_bearings, expected_turn_bearings); } diff --git a/unit_tests/util/coordinate_calculation.cpp b/unit_tests/util/coordinate_calculation.cpp index 4037e18b7..9ea47a307 100644 --- a/unit_tests/util/coordinate_calculation.cpp +++ b/unit_tests/util/coordinate_calculation.cpp @@ -420,7 +420,7 @@ BOOST_AUTO_TEST_CASE(computeArea) {FloatLongitude{.01}, FloatLatitude{-.01}}, {FloatLongitude{.00}, FloatLatitude{.00}}}; - BOOST_CHECK_CLOSE(2 * 1112.263 * 1112.263, computeArea(rhombus), 1e-3); + BOOST_CHECK_CLOSE(2 * 1109.462 * 1109.462, computeArea(rhombus), 1e-3); // edge cases auto self_intersection = std::vector{{FloatLongitude{.00}, FloatLatitude{.00}}, From 9d4dd2595eb5114166ddb902dae1b699e636144d Mon Sep 17 00:00:00 2001 From: Joonas Paalasmaa Date: Sat, 20 Aug 2022 19:14:38 +0300 Subject: [PATCH 02/12] Remove references to project-osrm.wolt.com (#6314) At Wolt, we are cleaning up subdomains under wolt.com, and project-osrm.wolt.com will go offline soon. --- docs/windows-deps.md | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/docs/windows-deps.md b/docs/windows-deps.md index 47fecc38a..a4965d265 100644 --- a/docs/windows-deps.md +++ b/docs/windows-deps.md @@ -12,20 +12,14 @@ Prepare directories for dependencies, build and target file location.Target dire ### Bzip2 -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/bzip2-1.0.8.tar.gz - * https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz - +1. Download from https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz 2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 3. Issue `nmake /f makefile.msc` 4. Copy bzlib.h to $target\include and libbz2.lib to $target\lib ### ZLib -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/zlib-1.2.11.tar.gz - * https://www.zlib.net/zlib-1.2.11.tar.gz - +1. Download https://www.zlib.net/zlib-1.2.11.tar.gz 2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 3. Switch to `contrib\vstudio\vc14` 4. If needed, open `zlibvc.sln` with Visual Studio and retarget to your version of compiler and SDK. @@ -34,10 +28,8 @@ Prepare directories for dependencies, build and target file location.Target dire ### ICU -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://wolt-project.wolt.com/deps/icu4c-66_1-src.zip +1. Download and unpack. * https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-src.zip - * https://wolt-project.wolt.com/deps/icu4c-66_1-data.zip * https://github.com/unicode-org/icu/releases/download/release-66-1/icu4c-66_1-data.zip 2. Do retarget if neededby openinig .\source\allinone\allinone.sln and editing projects 3. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. @@ -48,10 +40,7 @@ Prepare directories for dependencies, build and target file location.Target dire ### Boost -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/boost_1_73_0.zip - * https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.zip - +1. Download and unpack https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.zip 2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 3. Build b2: bootstrap.bat --with-toolset=msvc-14.2 @@ -61,9 +50,7 @@ Prepare directories for dependencies, build and target file location.Target dire ### Expat -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/libexpat-2_2_9.zip - * https://github.com/libexpat/libexpat/archive/R_2_2_9.zip +1. Download and unpack https://github.com/libexpat/libexpat/archive/R_2_2_9.zip 2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 3. Configure build my calling cmake: mkdir expat\build @@ -74,9 +61,7 @@ Prepare directories for dependencies, build and target file location.Target dire ### LUA -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/lua-5.3.5.tar.gz - * https://www.lua.org/ftp/lua-5.3.5.tar.gz +1. Download and unpack https://www.lua.org/ftp/lua-5.3.5.tar.gz 2. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 3. Lua doesn't have native MSVC support, so you have to compile it by hand: cd src @@ -88,9 +73,7 @@ Prepare directories for dependencies, build and target file location.Target dire ### TBB -1. Download either from Wolt OSRM mirror or original distribution and unpack. - * https://project-osrm.wolt.com/deps/oneTBB-v2020.2.zip - * https://github.com/oneapi-src/oneTBB/archive/v2020.2.zip +1. Download and unpack https://github.com/oneapi-src/oneTBB/archive/v2020.2.zip 2. Retarget by opening build\vs2013\makefile.sln 3. Start 'x64 Native Tools Command Prompt for VS2019' and change directory to unpacked source tree. 4. Switch to build\vs2013 and build: `msbuild makefle.sln /nologo /p:Configuration=Release /p:Platform=x64` From 47e5591ed8030602f913d0122f7084c4095654d4 Mon Sep 17 00:00:00 2001 From: Siarhei Fedartsou Date: Sat, 20 Aug 2022 18:16:05 +0200 Subject: [PATCH 03/12] Use the latest node on CI (#6317) --- .github/workflows/osrm-backend.yml | 13 +++++-------- CHANGELOG.md | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index ae4c1073e..4addd0564 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -46,7 +46,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: 12 - name: Enable Node.js cache @@ -348,8 +348,7 @@ jobs: - name: conan-osx-release-node-latest build_node_package: true continue-on-error: true - # TODO: Use node 'latest' once supported: https://github.com/actions/setup-node/issues/257 - node: 16 + node: latest runs-on: macos-11 BUILD_TYPE: Release CCOMPILER: clang @@ -361,8 +360,7 @@ jobs: - name: node-latest-conan-linux-release build_node_package: true continue-on-error: true - # TODO: Use node 'latest' once supported: https://github.com/actions/setup-node/issues/257 - node: 16 + node: latest runs-on: ubuntu-20.04 BUILD_TYPE: Release CLANG_VERSION: 6.0.0 @@ -373,8 +371,7 @@ jobs: - name: node-latest-conan-linux-debug build_node_package: true continue-on-error: true - # TODO: Use node 'latest' once supported: https://github.com/actions/setup-node/issues/257 - node: 16 + node: latest runs-on: ubuntu-20.04 BUILD_TYPE: Debug CLANG_VERSION: 6.0.0 @@ -444,7 +441,7 @@ jobs: - uses: actions/checkout@v2 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} - name: Enable Node.js cache diff --git a/CHANGELOG.md b/CHANGELOG.md index f4d1f62a3..fbf414455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285) - FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296) - Build: + - CHANGED: Use the latest node on CI. [#6317](https://github.com/Project-OSRM/osrm-backend/pull/6317) - CHANGED: Migrate Windows CI to GitHub Actions. [#6312](https://github.com/Project-OSRM/osrm-backend/pull/6312) - ADDED: Add smoke test for Docker image. [#6313](https://github.com/Project-OSRM/osrm-backend/pull/6313) - CHANGED: Update libosmium to version 2.18.0. [#6303](https://github.com/Project-OSRM/osrm-backend/pull/6303) From e872f1d6c36d9eb2cf843149bf27598bffe291b7 Mon Sep 17 00:00:00 2001 From: Siarhei Fedartsou Date: Sat, 20 Aug 2022 18:27:14 +0200 Subject: [PATCH 04/12] Do not use deprecated Callback::Call overload in Node bindings (#6318) --- CHANGELOG.md | 1 + src/nodejs/node_osrm.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf414455..d9ed1703e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - Misc: + - CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318) - FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315) - FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304) - CHANGED: Pass osm_node_ids by reference in osrm::updater::Updater class. [#6298](https://github.com/Project-OSRM/osrm-backend/pull/6298) diff --git a/src/nodejs/node_osrm.cpp b/src/nodejs/node_osrm.cpp index ebd3b3fbf..5c8c486a5 100644 --- a/src/nodejs/node_osrm.cpp +++ b/src/nodejs/node_osrm.cpp @@ -148,7 +148,7 @@ inline void async(const Nan::FunctionCallbackInfo &info, ServiceMemFn service, Nan::Callback *callback, PluginParameters pluginParams_) - : Base(callback), osrm{std::move(osrm_)}, service{std::move(service)}, + : Base(callback, "osrm:async"), osrm{std::move(osrm_)}, service{std::move(service)}, params{std::move(params_)}, pluginParams{std::move(pluginParams_)} { } @@ -184,7 +184,7 @@ inline void async(const Nan::FunctionCallbackInfo &info, const constexpr auto argc = 2u; v8::Local argv[argc] = {Nan::Null(), render(result)}; - callback->Call(argc, argv); + callback->Call(argc, argv, async_resource); } // Keeps the OSRM object alive even after shutdown until we're done with callback @@ -230,8 +230,9 @@ inline void asyncForTiles(const Nan::FunctionCallbackInfo &info, ServiceMemFn service, Nan::Callback *callback, PluginParameters pluginParams_) - : Base(callback), osrm{std::move(osrm_)}, service{std::move(service)}, - params{std::move(params_)}, pluginParams{std::move(pluginParams_)} + : Base(callback, "osrm:asyncForTiles"), osrm{std::move(osrm_)}, + service{std::move(service)}, params{std::move(params_)}, pluginParams{ + std::move(pluginParams_)} { } @@ -256,7 +257,7 @@ inline void asyncForTiles(const Nan::FunctionCallbackInfo &info, auto str_result = result.get(); v8::Local argv[argc] = {Nan::Null(), render(str_result)}; - callback->Call(argc, argv); + callback->Call(argc, argv, async_resource); } // Keeps the OSRM object alive even after shutdown until we're done with callback From 7f014bd61664d1b34cee52680378780156629e0a Mon Sep 17 00:00:00 2001 From: Michael Bell Date: Tue, 1 Jun 2021 20:48:12 +0100 Subject: [PATCH 05/12] Clarify identifier types used in data facade The data facade interface contains numerous methods for looking up datapoints by identifiers. Many of the parameters use the NodeID or EdgeID types. However, these two identifier types are used for representing three different contexts: 1. Node-based graph edges and nodes 2. Edge-based graph edges and nodes 3. Packed geometries Consider the use of identifier parameters in these examples: --- GetWeightPenaltyForEdgeID(const EdgeID id) <- edge-based edge GetUncompressedForwardWeights(const EdgeID id) <- packed geometry IsLeftHandDriving(const NodeID id) <- edge-based node GetBearingClass(const NodeID node) <- node-based node --- This mixing of contexts within the same interface makes it difficult to understand the relationships and dependencies between the OSRM datasets. For 1. and 2. we continue to use the NodeID and EdgeID types, but change the interface parameter names to identify them as edge-based or node-based graph properties. For 3. we define a new type definition, PackedGeometryID. These changes are to aid with readability. A next step would be to strongly type these definitions, leveraging the Alias template already used for OSM identifiers. --- CHANGELOG.md | 1 + .../datafacade/algorithm_datafacade.hpp | 48 +++-- .../contiguous_internalmem_datafacade.hpp | 201 ++++++++++-------- include/engine/datafacade/datafacade_base.hpp | 59 ++--- include/util/typedefs.hpp | 20 +- 5 files changed, 175 insertions(+), 154 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ed1703e..6d9c9d58f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - CHANGED: Pass osm_node_ids by reference in osrm::updater::Updater class. [#6298](https://github.com/Project-OSRM/osrm-backend/pull/6298) - FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285) - FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296) + - FIXED: Internal refactoring of identifier types used in data facade [#6044](https://github.com/Project-OSRM/osrm-backend/pull/6044) - Build: - CHANGED: Use the latest node on CI. [#6317](https://github.com/Project-OSRM/osrm-backend/pull/6317) - CHANGED: Migrate Windows CI to GitHub Actions. [#6312](https://github.com/Project-OSRM/osrm-backend/pull/6312) diff --git a/include/engine/datafacade/algorithm_datafacade.hpp b/include/engine/datafacade/algorithm_datafacade.hpp index 38030511c..4ccbf5af3 100644 --- a/include/engine/datafacade/algorithm_datafacade.hpp +++ b/include/engine/datafacade/algorithm_datafacade.hpp @@ -36,24 +36,27 @@ template <> class AlgorithmDataFacade virtual unsigned GetNumberOfEdges() const = 0; - virtual unsigned GetOutDegree(const NodeID n) const = 0; + virtual unsigned GetOutDegree(const NodeID edge_based_node_id) const = 0; - virtual NodeID GetTarget(const EdgeID e) const = 0; + virtual NodeID GetTarget(const EdgeID edge_based_edge_id) const = 0; - virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0; + virtual const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const = 0; - virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; + virtual EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const = 0; // searches for a specific edge - virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; + virtual EdgeID FindEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const = 0; - virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0; + virtual EdgeID FindEdgeInEitherDirection(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const = 0; - virtual EdgeID - FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0; + virtual EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from, + const NodeID edge_based_node_to, + bool &result) const = 0; - virtual EdgeID FindSmallestEdge(const NodeID from, - const NodeID to, + virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to, const std::function filter) const = 0; }; @@ -70,23 +73,24 @@ template <> class AlgorithmDataFacade virtual unsigned GetNumberOfEdges() const = 0; - virtual unsigned GetOutDegree(const NodeID n) const = 0; + virtual unsigned GetOutDegree(const NodeID edge_based_node_id) const = 0; - virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; + virtual EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const = 0; - virtual EdgeWeight GetNodeWeight(const NodeID node) const = 0; + virtual EdgeWeight GetNodeWeight(const NodeID edge_based_node_id) const = 0; - virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed + virtual EdgeWeight + GetNodeDuration(const NodeID edge_based_node_id) const = 0; // TODO: to be removed - virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0; + virtual EdgeDistance GetNodeDistance(const NodeID edge_based_node_id) const = 0; - virtual bool IsForwardEdge(EdgeID edge) const = 0; + virtual bool IsForwardEdge(EdgeID edge_based_edge_id) const = 0; - virtual bool IsBackwardEdge(EdgeID edge) const = 0; + virtual bool IsBackwardEdge(EdgeID edge_based_edge_id) const = 0; - virtual NodeID GetTarget(const EdgeID e) const = 0; + virtual NodeID GetTarget(const EdgeID edge_based_edge_id) const = 0; - virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0; + virtual const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const = 0; virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0; @@ -94,10 +98,12 @@ template <> class AlgorithmDataFacade virtual const customizer::CellMetricView &GetCellMetric() const = 0; - virtual EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const = 0; + virtual EdgeRange GetBorderEdgeRange(const LevelID level, + const NodeID edge_based_node_id) const = 0; // searches for a specific edge - virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; + virtual EdgeID FindEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const = 0; }; } // namespace datafacade } // namespace engine diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index e448a8f57..d426ed84f 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -73,45 +73,52 @@ class ContiguousInternalMemoryAlgorithmDataFacade : public datafacade::Algor unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const override final + unsigned GetOutDegree(const NodeID edge_based_node_id) const override final { - return m_query_graph.GetOutDegree(n); + return m_query_graph.GetOutDegree(edge_based_node_id); } - NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); } - - const EdgeData &GetEdgeData(const EdgeID e) const override final + NodeID GetTarget(const EdgeID edge_based_edge_id) const override final { - return m_query_graph.GetEdgeData(e); + return m_query_graph.GetTarget(edge_based_edge_id); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final + const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const override final { - return m_query_graph.GetAdjacentEdgeRange(node); + return m_query_graph.GetEdgeData(edge_based_edge_id); + } + + EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const override final + { + return m_query_graph.GetAdjacentEdgeRange(edge_based_node_id); } // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const override final + EdgeID FindEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const override final { - return m_query_graph.FindEdge(from, to); + return m_query_graph.FindEdge(edge_based_node_from, edge_based_node_to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final + EdgeID FindEdgeInEitherDirection(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const override final { - return m_query_graph.FindEdgeInEitherDirection(from, to); + return m_query_graph.FindEdgeInEitherDirection(edge_based_node_from, edge_based_node_to); } - EdgeID - FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final + EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from, + const NodeID edge_based_node_to, + bool &result) const override final { - return m_query_graph.FindEdgeIndicateIfReverse(from, to, result); + return m_query_graph.FindEdgeIndicateIfReverse( + edge_based_node_from, edge_based_node_to, result); } - EdgeID FindSmallestEdge(const NodeID from, - const NodeID to, + EdgeID FindSmallestEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to, std::function filter) const override final { - return m_query_graph.FindSmallestEdge(from, to, filter); + return m_query_graph.FindSmallestEdge(edge_based_node_from, edge_based_node_to, filter); } }; @@ -126,11 +133,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade { private: using super = BaseDataFacade; - using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT; using RTreeLeaf = super::RTreeLeaf; using SharedRTree = util::StaticRTree; using SharedGeospatialQuery = GeospatialQuery; - using RTreeNode = SharedRTree::TreeNode; extractor::ClassData exclude_mask; extractor::ProfileProperties *m_profile_properties; @@ -231,76 +236,80 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade } // node and edge information access - util::Coordinate GetCoordinateOfNode(const NodeID id) const override final + util::Coordinate GetCoordinateOfNode(const NodeID node_based_node_id) const override final { - return m_coordinate_list[id]; + return m_coordinate_list[node_based_node_id]; } - OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final + OSMNodeID GetOSMNodeIDOfNode(const NodeID node_based_node_id) const override final { - return m_osmnodeid_list[id]; + return m_osmnodeid_list[node_based_node_id]; } - NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const override final + NodeForwardRange GetUncompressedForwardGeometry(const PackedGeometryID id) const override final { return segment_data.GetForwardGeometry(id); } - NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const override final + NodeReverseRange GetUncompressedReverseGeometry(const PackedGeometryID id) const override final { return segment_data.GetReverseGeometry(id); } - DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const override final + DurationForwardRange + GetUncompressedForwardDurations(const PackedGeometryID id) const override final { return segment_data.GetForwardDurations(id); } - DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const override final + DurationReverseRange + GetUncompressedReverseDurations(const PackedGeometryID id) const override final { return segment_data.GetReverseDurations(id); } - WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const override final + WeightForwardRange GetUncompressedForwardWeights(const PackedGeometryID id) const override final { return segment_data.GetForwardWeights(id); } - WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const override final + WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const override final { return segment_data.GetReverseWeights(id); } // Returns the data source ids that were used to supply the edge // weights. - DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const override final + DatasourceForwardRange + GetUncompressedForwardDatasources(const PackedGeometryID id) const override final { return segment_data.GetForwardDatasources(id); } // Returns the data source ids that were used to supply the edge // weights. - DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const override final + DatasourceReverseRange + GetUncompressedReverseDatasources(const PackedGeometryID id) const override final { return segment_data.GetReverseDatasources(id); } - TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final + TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID edge_based_edge_id) const override final { - BOOST_ASSERT(m_turn_weight_penalties.size() > id); - return m_turn_weight_penalties[id]; + BOOST_ASSERT(m_turn_weight_penalties.size() > edge_based_edge_id); + return m_turn_weight_penalties[edge_based_edge_id]; } - TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final + TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID edge_based_edge_id) const override final { - BOOST_ASSERT(m_turn_duration_penalties.size() > id); - return m_turn_duration_penalties[id]; + BOOST_ASSERT(m_turn_duration_penalties.size() > edge_based_edge_id); + return m_turn_duration_penalties[edge_based_edge_id]; } osrm::guidance::TurnInstruction - GetTurnInstructionForEdgeID(const EdgeID id) const override final + GetTurnInstructionForEdgeID(const EdgeID edge_based_edge_id) const override final { - return turn_data.GetTurnInstruction(id); + return turn_data.GetTurnInstruction(edge_based_edge_id); } std::vector GetEdgesInBox(const util::Coordinate south_west, @@ -444,29 +453,29 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade return std::string(m_data_timestamp.begin(), m_data_timestamp.end()); } - GeometryID GetGeometryIndex(const NodeID id) const override final + GeometryID GetGeometryIndex(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.GetGeometryID(id); + return edge_based_node_data.GetGeometryID(edge_based_node_id); } - ComponentID GetComponentID(const NodeID id) const override final + ComponentID GetComponentID(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.GetComponentID(id); + return edge_based_node_data.GetComponentID(edge_based_node_id); } - extractor::TravelMode GetTravelMode(const NodeID id) const override final + extractor::TravelMode GetTravelMode(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.GetTravelMode(id); + return edge_based_node_data.GetTravelMode(edge_based_node_id); } - extractor::ClassData GetClassData(const NodeID id) const override final + extractor::ClassData GetClassData(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.GetClassData(id); + return edge_based_node_data.GetClassData(edge_based_node_id); } - bool ExcludeNode(const NodeID id) const override final + bool ExcludeNode(const NodeID edge_based_node_id) const override final { - return (edge_based_node_data.GetClassData(id) & exclude_mask) > 0; + return (edge_based_node_data.GetClassData(edge_based_node_id) & exclude_mask) > 0; } std::vector GetClasses(const extractor::ClassData class_data) const override final @@ -480,9 +489,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade return classes; } - NameID GetNameIndex(const NodeID id) const override final + NameID GetNameIndex(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.GetNameID(id); + return edge_based_node_data.GetNameID(edge_based_node_id); } StringView GetNameForID(const NameID id) const override final @@ -537,32 +546,37 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade return m_profile_properties->GetWeightMultiplier(); } - util::guidance::BearingClass GetBearingClass(const NodeID node) const override final + util::guidance::BearingClass + GetBearingClass(const NodeID node_based_node_id) const override final { - return intersection_bearings_view.GetBearingClass(node); + return intersection_bearings_view.GetBearingClass(node_based_node_id); } - guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final + guidance::TurnBearing PreTurnBearing(const EdgeID edge_based_edge_id) const override final { - return turn_data.GetPreTurnBearing(eid); + return turn_data.GetPreTurnBearing(edge_based_edge_id); } - guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final + guidance::TurnBearing PostTurnBearing(const EdgeID edge_based_edge_id) const override final { - return turn_data.GetPostTurnBearing(eid); + return turn_data.GetPostTurnBearing(edge_based_edge_id); } - util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const override final + util::guidance::EntryClass GetEntryClass(const EdgeID edge_based_edge_id) const override final { - auto entry_class_id = turn_data.GetEntryClassID(turn_id); + auto entry_class_id = turn_data.GetEntryClassID(edge_based_edge_id); return m_entry_class_table.at(entry_class_id); } - bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); } - - util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final + bool HasLaneData(const EdgeID edge_based_edge_id) const override final { - BOOST_ASSERT(HasLaneData(id)); - return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id)); + return turn_data.HasLaneData(edge_based_edge_id); + } + + util::guidance::LaneTupleIdPair + GetLaneData(const EdgeID edge_based_edge_id) const override final + { + BOOST_ASSERT(HasLaneData(edge_based_edge_id)); + return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(edge_based_edge_id)); } extractor::TurnLaneDescription @@ -577,15 +591,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade m_lane_description_offsets[lane_description_id + 1]); } - bool IsLeftHandDriving(const NodeID id) const override final + bool IsLeftHandDriving(const NodeID edge_based_node_id) const override final { // TODO: can be moved to a data block indexed by GeometryID - return edge_based_node_data.IsLeftHandDriving(id); + return edge_based_node_data.IsLeftHandDriving(edge_based_node_id); } - bool IsSegregated(const NodeID id) const override final + bool IsSegregated(const NodeID edge_based_node_id) const override final { - return edge_based_node_data.IsSegregated(id); + return edge_based_node_data.IsSegregated(edge_based_node_id); } std::vector @@ -691,57 +705,62 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade : public Algo unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const override final + unsigned GetOutDegree(const NodeID edge_based_node_id) const override final { - return query_graph.GetOutDegree(n); + return query_graph.GetOutDegree(edge_based_node_id); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final + EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const override final { - return query_graph.GetAdjacentEdgeRange(node); + return query_graph.GetAdjacentEdgeRange(edge_based_node_id); } - EdgeWeight GetNodeWeight(const NodeID node) const override final + EdgeWeight GetNodeWeight(const NodeID edge_based_node_id) const override final { - return query_graph.GetNodeWeight(node); + return query_graph.GetNodeWeight(edge_based_node_id); } - EdgeDuration GetNodeDuration(const NodeID node) const override final + EdgeDuration GetNodeDuration(const NodeID edge_based_node_id) const override final { - return query_graph.GetNodeDuration(node); + return query_graph.GetNodeDuration(edge_based_node_id); } - EdgeDistance GetNodeDistance(const NodeID node) const override final + EdgeDistance GetNodeDistance(const NodeID edge_based_node_id) const override final { - return query_graph.GetNodeDistance(node); + return query_graph.GetNodeDistance(edge_based_node_id); } - bool IsForwardEdge(const NodeID node) const override final + bool IsForwardEdge(const NodeID edge_based_node_id) const override final { - return query_graph.IsForwardEdge(node); + return query_graph.IsForwardEdge(edge_based_node_id); } - bool IsBackwardEdge(const NodeID node) const override final + bool IsBackwardEdge(const NodeID edge_based_node_id) const override final { - return query_graph.IsBackwardEdge(node); + return query_graph.IsBackwardEdge(edge_based_node_id); } - NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); } - - const EdgeData &GetEdgeData(const EdgeID e) const override final + NodeID GetTarget(const EdgeID edge_based_edge_id) const override final { - return query_graph.GetEdgeData(e); + return query_graph.GetTarget(edge_based_edge_id); } - EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final + const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const override final { - return query_graph.GetBorderEdgeRange(level, node); + return query_graph.GetEdgeData(edge_based_edge_id); + } + + EdgeRange GetBorderEdgeRange(const LevelID level, + const NodeID edge_based_node_id) const override final + { + return query_graph.GetBorderEdgeRange(level, edge_based_node_id); } // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const override final + EdgeID FindEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to) const override final { - return query_graph.FindEdge(from, to); + return query_graph.FindEdge(edge_based_node_from, edge_based_node_to); } }; diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index b80c93b18..153810fdd 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -77,46 +77,51 @@ class BaseDataFacade virtual std::string GetTimestamp() const = 0; // node and edge information access - virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0; + virtual util::Coordinate GetCoordinateOfNode(const NodeID node_based_node_id) const = 0; - virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const = 0; + virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID node_based_node_id) const = 0; - virtual GeometryID GetGeometryIndex(const NodeID id) const = 0; + virtual GeometryID GetGeometryIndex(const NodeID edge_based_node_id) const = 0; - virtual ComponentID GetComponentID(const NodeID id) const = 0; + virtual ComponentID GetComponentID(const NodeID edge_based_node_id) const = 0; - virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0; - virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0; + virtual NodeForwardRange GetUncompressedForwardGeometry(const PackedGeometryID id) const = 0; + virtual NodeReverseRange GetUncompressedReverseGeometry(const PackedGeometryID id) const = 0; - virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const = 0; + virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID edge_based_edge_id) const = 0; - virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const = 0; + virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID edge_based_edge_id) const = 0; // Gets the weight values for each segment in an uncompressed geometry. // Should always be 1 shorter than GetUncompressedGeometry - virtual WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const = 0; - virtual WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const = 0; + virtual WeightForwardRange GetUncompressedForwardWeights(const PackedGeometryID id) const = 0; + virtual WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const = 0; // Gets the duration values for each segment in an uncompressed geometry. // Should always be 1 shorter than GetUncompressedGeometry - virtual DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const = 0; - virtual DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const = 0; + virtual DurationForwardRange + GetUncompressedForwardDurations(const PackedGeometryID id) const = 0; + virtual DurationReverseRange + GetUncompressedReverseDurations(const PackedGeometryID id) const = 0; // Returns the data source ids that were used to supply the edge // weights. Will return an empty array when only the base profile is used. - virtual DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const = 0; - virtual DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const = 0; + virtual DatasourceForwardRange + GetUncompressedForwardDatasources(const PackedGeometryID id) const = 0; + virtual DatasourceReverseRange + GetUncompressedReverseDatasources(const PackedGeometryID id) const = 0; // Gets the name of a datasource virtual StringView GetDatasourceName(const DatasourceID id) const = 0; - virtual osrm::guidance::TurnInstruction GetTurnInstructionForEdgeID(const EdgeID id) const = 0; + virtual osrm::guidance::TurnInstruction + GetTurnInstructionForEdgeID(const EdgeID edge_based_edge_id) const = 0; - virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0; + virtual extractor::TravelMode GetTravelMode(const NodeID edge_based_node_id) const = 0; - virtual extractor::ClassData GetClassData(const NodeID id) const = 0; + virtual extractor::ClassData GetClassData(const NodeID edge_based_node_id) const = 0; - virtual bool ExcludeNode(const NodeID id) const = 0; + virtual bool ExcludeNode(const NodeID edge_based_node_id) const = 0; virtual std::vector GetClasses(const extractor::ClassData class_data) const = 0; @@ -182,12 +187,12 @@ class BaseDataFacade const Approach approach, const bool use_all_edges = false) const = 0; - virtual bool HasLaneData(const EdgeID id) const = 0; - virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0; + virtual bool HasLaneData(const EdgeID edge_based_edge_id) const = 0; + virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID edge_based_edge_id) const = 0; virtual extractor::TurnLaneDescription GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0; - virtual NameID GetNameIndex(const NodeID id) const = 0; + virtual NameID GetNameIndex(const NodeID edge_based_node_id) const = 0; virtual StringView GetNameForID(const NameID id) const = 0; @@ -209,16 +214,16 @@ class BaseDataFacade virtual double GetWeightMultiplier() const = 0; - virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0; - virtual osrm::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0; + virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID edge_based_edge_id) const = 0; + virtual osrm::guidance::TurnBearing PostTurnBearing(const EdgeID edge_based_edge_id) const = 0; - virtual util::guidance::BearingClass GetBearingClass(const NodeID node) const = 0; + virtual util::guidance::BearingClass GetBearingClass(const NodeID node_based_node_id) const = 0; - virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0; + virtual util::guidance::EntryClass GetEntryClass(const EdgeID edge_based_edge_id) const = 0; - virtual bool IsLeftHandDriving(const NodeID id) const = 0; + virtual bool IsLeftHandDriving(const NodeID edge_based_node_id) const = 0; - virtual bool IsSegregated(const NodeID) const = 0; + virtual bool IsSegregated(const NodeID edge_based_node_id) const = 0; virtual std::vector GetOverridesThatStartAt(const NodeID edge_based_node_id) const = 0; diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index 9868ee2ff..b1e962e2e 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -76,13 +76,13 @@ using NodeID = std::uint32_t; using EdgeID = std::uint32_t; using NameID = std::uint32_t; using AnnotationID = std::uint32_t; +using PackedGeometryID = std::uint32_t; using EdgeWeight = std::int32_t; using EdgeDuration = std::int32_t; using EdgeDistance = float; using SegmentWeight = std::uint32_t; using SegmentDuration = std::uint32_t; using TurnPenalty = std::int16_t; // turn penalty in 100ms units -using DataTimestamp = std::string; static const std::size_t INVALID_INDEX = std::numeric_limits::max(); @@ -95,16 +95,13 @@ static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID = std::numeric_limits::max(); using BearingClassID = std::uint32_t; -static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits::max(); - using DiscreteBearing = std::uint16_t; - using EntryClassID = std::uint16_t; -static const EntryClassID INVALID_ENTRY_CLASSID = std::numeric_limits::max(); static const NodeID SPECIAL_NODEID = std::numeric_limits::max(); static const NodeID SPECIAL_SEGMENTID = std::numeric_limits::max() >> 1; -static const NodeID SPECIAL_GEOMETRYID = std::numeric_limits::max() >> 1; +static const PackedGeometryID SPECIAL_GEOMETRYID = + std::numeric_limits::max() >> 1; static const EdgeID SPECIAL_EDGEID = std::numeric_limits::max(); static const RestrictionID SPECIAL_RESTRICTIONID = std::numeric_limits::max(); static const NameID INVALID_NAMEID = std::numeric_limits::max(); @@ -123,13 +120,6 @@ static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits::max(); static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits::max(); -// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent -// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any -// min() / operator< checks due to the invalid truncation. In addition, using signed and unsigned -// weights produces problems. As a result we can only store 1 << 29 since the MSB is still reserved -// for the sign bit. See https://github.com/Project-OSRM/osrm-backend/issues/3677 -static const EdgeWeight MAXIMAL_EDGE_DURATION_INT_30 = (1 << 29) - 1; - using DatasourceID = std::uint8_t; using BisectionID = std::uint32_t; @@ -158,11 +148,11 @@ struct SegmentID */ struct GeometryID { - GeometryID(const NodeID id_, const bool forward_) : id{id_}, forward{forward_} {} + GeometryID(const PackedGeometryID id_, const bool forward_) : id{id_}, forward{forward_} {} GeometryID() : id(std::numeric_limits::max() >> 1), forward(false) {} - NodeID id : 31; + PackedGeometryID id : 31; std::uint32_t forward : 1; }; From e3c7995b00409f3da335300f7ca3d212a69602a4 Mon Sep 17 00:00:00 2001 From: Rafael Guglielmetti Date: Mon, 22 Aug 2022 08:32:25 +0200 Subject: [PATCH 06/12] Add missing files in exception message (#5360) --- CHANGELOG.md | 1 + include/storage/io_config.hpp | 1 + src/osrm/osrm.cpp | 9 +++++++-- src/storage/io_config.cpp | 18 ++++++++++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9c9d58f..ed93059d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - Misc: + - CHANGED: missing files list is included in exception message. [#5360](https://github.com/Project-OSRM/osrm-backend/pull/5360) - CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318) - FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315) - FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304) diff --git a/include/storage/io_config.hpp b/include/storage/io_config.hpp index 577291ee1..831382df7 100644 --- a/include/storage/io_config.hpp +++ b/include/storage/io_config.hpp @@ -25,6 +25,7 @@ struct IOConfig } bool IsValid() const; + std::vector GetMissingFiles() const; boost::filesystem::path GetPath(const std::string &fileName) const { if (!IsConfigured(fileName, required_input_files) && diff --git a/src/osrm/osrm.cpp b/src/osrm/osrm.cpp index 8871aff45..83e1076f7 100644 --- a/src/osrm/osrm.cpp +++ b/src/osrm/osrm.cpp @@ -10,6 +10,8 @@ #include "engine/engine_config.hpp" #include "engine/status.hpp" +#include + #include namespace osrm @@ -25,8 +27,11 @@ OSRM::OSRM(engine::EngineConfig &config) // First, check that necessary core data is available if (!config.use_shared_memory && !config.storage_config.IsValid()) { - throw util::exception("Required files are missing, cannot continue. Have all the " - "pre-processing steps been run?"); + const auto &missingFiles = config.storage_config.GetMissingFiles(); + throw util::exception("Required files are missing, cannot continue. Have all the " + "pre-processing steps been run? " + "Missing files: " + + boost::algorithm::join(missingFiles, ", ")); } // Now, check that the algorithm requested can be used with the data diff --git a/src/storage/io_config.cpp b/src/storage/io_config.cpp index e100a9317..cd05d2d76 100644 --- a/src/storage/io_config.cpp +++ b/src/storage/io_config.cpp @@ -10,10 +10,11 @@ namespace osrm { namespace storage { + +namespace fs = boost::filesystem; + bool IOConfig::IsValid() const { - namespace fs = boost::filesystem; - bool success = true; for (auto &fileName : required_input_files) { @@ -26,5 +27,18 @@ bool IOConfig::IsValid() const } return success; } + +std::vector IOConfig::GetMissingFiles() const +{ + std::vector missingFiles; + for (auto &fileName : required_input_files) + { + if (!fs::is_regular_file(fs::path(base_path.string() + fileName.string()))) + { + missingFiles.push_back(base_path.string() + fileName.string()); + } + } + return missingFiles; +} } // namespace storage } // namespace osrm From b4b1aea567db245c7336ed5a7fd1eb0ddd0c70e5 Mon Sep 17 00:00:00 2001 From: Michael Bell Date: Mon, 22 Aug 2022 12:56:47 +0100 Subject: [PATCH 07/12] Add support for non-round-trips with a single fixed endpoint (#6050) Currently /trip supports finding round-trip routes where only the start or end location is fixed. This PR extends this feature to non-round-trip requests. We do this by a new table manipulation that simulates non-round-trip fixed endpoint requests as a round-trip request. --- CHANGELOG.md | 2 + docs/http.md | 4 +- features/step_definitions/trip.js | 6 +- features/testbot/trip.feature | 130 ++++++++++++++------ features/testbot/zero-speed-updates.feature | 4 +- src/engine/plugins/trip.cpp | 73 +++++++---- test/nodejs/trip.js | 55 +++++---- unit_tests/library/trip.cpp | 8 +- 8 files changed, 188 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed93059d5..8b577c71f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ - FIXED: Fixed Node docs generation check in CI. [#6058](https://github.com/Project-OSRM/osrm-backend/pull/6058) - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) + - Routing: + - ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050) # 5.26.0 - Changes from 5.25.0 diff --git a/docs/http.md b/docs/http.md index 60149856b..acdc1cd4f 100644 --- a/docs/http.md +++ b/docs/http.md @@ -507,8 +507,8 @@ Right now, the following combinations are possible: | true | any | last | **yes** | | true | any | any | **yes** | | false | first | last | **yes** | -| false | first | any | no | -| false | any | last | no | +| false | first | any | **yes** | +| false | any | last | **yes** | | false | any | any | no | #### Example Requests diff --git a/features/step_definitions/trip.js b/features/step_definitions/trip.js index e72044018..ab2f7c35e 100644 --- a/features/step_definitions/trip.js +++ b/features/step_definitions/trip.js @@ -61,7 +61,8 @@ module.exports = function () { var subTrips; var trip_durations; var trip_distance; - if (res.statusCode === 200) { + var ok = res.statusCode === 200; + if (ok) { if (headers.has('trips')) { subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => { var toAdd = []; @@ -84,8 +85,7 @@ module.exports = function () { } } - var ok = true, - encodedResult = ''; + var encodedResult = ''; if (json.trips) row.trips.split(',').forEach((sub, si) => { if (si >= subTrips.length) { diff --git a/features/testbot/trip.feature b/features/testbot/trip.feature index 9fe3c23ae..840aadb9c 100644 --- a/features/testbot/trip.feature +++ b/features/testbot/trip.feature @@ -5,7 +5,7 @@ Feature: Basic trip planning Given the profile "testbot" Given a grid size of 10 meters - Scenario: Testbot - Trip: Roundtrip with one waypoint + Scenario: Testbot - Trip: Roundtrip between same waypoint Given the node map """ a b @@ -21,7 +21,7 @@ Feature: Basic trip planning When I plan a trip I should get | waypoints | trips | - | a | aa | + | a,a | aa | Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10) Given the node map @@ -69,36 +69,37 @@ Feature: Basic trip planning | waypoints | trips | | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | - Scenario: Testbot - Trip: Roundtrip FS waypoints (more than 10) - Given the node map - """ - a b c d - l e - k f - j i h g - """ - - And the ways - | nodes | - | ab | - | bc | - | de | - | ef | - | fg | - | gh | - | hi | - | ij | - | jk | - | kl | - | la | - - When I plan a trip I should get - | waypoints | source | trips | - | a,b,c,d,e,f,g,h,i,j,k,l | first | alkjihgfedcba | - - Scenario: Testbot - Trip: Roundtrip FE waypoints (more than 10) + Scenario: Testbot - Trip: FS waypoints (less than 10) Given the query options - | source | last | + | source | first | + Given the node map + """ + a b c d + l e + + j i g + """ + + And the ways + | nodes | + | ab | + | bc | + | de | + | eg | + | gi | + | ij | + | jl | + | la | + + When I plan a trip I should get + | waypoints | trips | roundtrip | durations | + | a,b,c,d,e,g,i,j,l | abcdegijla | true | 22 | + | a,b,c,d,e,g,i,j,l | abcljiged | false | 13 | + + + Scenario: Testbot - Trip: FS waypoints (more than 10) + Given the query options + | source | first | Given the node map """ a b c d @@ -122,8 +123,67 @@ Feature: Basic trip planning | la | When I plan a trip I should get - | waypoints | trips | - | a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | + | waypoints | trips | roundtrip | durations | + | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | true | 22 | + | a,b,c,d,e,f,g,h,i,j,k,l | acblkjihgfed | false | 13 | + + + Scenario: Testbot - Trip: FE waypoints (less than 10) + Given the query options + | destination | last | + Given the node map + """ + a b c d + l e + + j i g + """ + + And the ways + | nodes | + | ab | + | bc | + | de | + | eg | + | gi | + | ij | + | jl | + | la | + + When I plan a trip I should get + | waypoints | trips | roundtrip | durations | + | a,b,c,d,e,g,i,j,l | labcdegijl | true | 22 | + | a,b,c,d,e,g,i,j,l | degijabcl | false | 14 | + + Scenario: Testbot - Trip: FE waypoints (more than 10) + Given the query options + | destination | last | + Given the node map + """ + a b c d + l e + k f + j i h g + """ + + And the ways + | nodes | + | ab | + | bc | + | de | + | ef | + | fg | + | gh | + | hi | + | ij | + | jk | + | kl | + | la | + + When I plan a trip I should get + | waypoints | trips | roundtrip | durations | + | a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | true | 22 | + | a,b,c,d,e,f,g,h,i,j,k,l | cbakjihgfedl | false | 19 | Scenario: Testbot - Trip: Unroutable roundtrip with waypoints (less than 10) Given the node map @@ -274,7 +334,7 @@ Feature: Basic trip planning | a,b,d,e,c | first | last | true | abedca | - Scenario: Testbot - Trip: midway points in isoldated roads should return no trips + Scenario: Testbot - Trip: midway points in isolated roads should return no trips Given the node map """ a 1 b @@ -370,4 +430,4 @@ Feature: Basic trip planning When I plan a trip I should get | waypoints | trips | durations | geometry | | a,b,c,d | abcda | 7.6 | 1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009,1,1 | - | d,b,c,a | dbcad | 7.6 | 0.99991,1.00009,1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009 | \ No newline at end of file + | d,b,c,a | dbcad | 7.6 | 0.99991,1.00009,1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009 | diff --git a/features/testbot/zero-speed-updates.feature b/features/testbot/zero-speed-updates.feature index c2bc82c94..ae5a99c7f 100644 --- a/features/testbot/zero-speed-updates.feature +++ b/features/testbot/zero-speed-updates.feature @@ -187,5 +187,5 @@ Feature: Check zero speed updates When I plan a trip I should get | waypoints | trips | code | - | a,b,c,d | abcda | NoTrips | - | d,b,c,a | dbcad | NoTrips | + | a,b,c,d | | NoTrips | + | d,b,c,a | | NoTrips | diff --git a/src/engine/plugins/trip.cpp b/src/engine/plugins/trip.cpp index d949fcb60..20daf95d9 100644 --- a/src/engine/plugins/trip.cpp +++ b/src/engine/plugins/trip.cpp @@ -36,18 +36,7 @@ bool IsSupportedParameterCombination(const bool fixed_start, const bool fixed_end, const bool roundtrip) { - if (fixed_start && fixed_end && !roundtrip) - { - return true; - } - else if (roundtrip) - { - return true; - } - else - { - return false; - } + return roundtrip || fixed_start || fixed_end; } // given the node order in which to visit, compute the actual route (with geometry, travel time and @@ -142,6 +131,32 @@ void ManipulateTableForFSE(const std::size_t source_id, //********* End of changes to table ************************************* } +void ManipulateTableForNonRoundtripFS(const std::size_t source_id, + util::DistTableWrapper &result_table) +{ + // We can use the round-trip calculation to simulate non-round-trip fixed start + // by making all paths to the source location zero. Effectively finding an 'optimal' + // round-trip path that ignores the cost of getting back from any destination to the + // source. + for (const auto i : util::irange(0, result_table.GetNumberOfNodes())) + { + result_table.SetValue(i, source_id, 0); + } +} + +void ManipulateTableForNonRoundtripFE(const std::size_t destination_id, + util::DistTableWrapper &result_table) +{ + // We can use the round-trip calculation to simulate non-round-trip fixed end + // by making all paths from the destination to other locations zero. + // Effectively, finding an 'optimal' round-trip path that ignores the cost of getting + // from the destination to any source. + for (const auto i : util::irange(0, result_table.GetNumberOfNodes())) + { + result_table.SetValue(destination_id, i, 0); + } +} + Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, const api::TripParameters ¶meters, osrm::engine::api::ResultT &result) const @@ -225,7 +240,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, return Status::Error; } - const constexpr std::size_t BF_MAX_FEASABLE = 10; + const constexpr std::size_t BF_MAX_FEASIBLE = 10; BOOST_ASSERT_MSG(result_duration_table.size() == number_of_locations * number_of_locations, "Distance Table has wrong size"); @@ -238,11 +253,19 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, { ManipulateTableForFSE(source_id, destination_id, result_duration_table); } + else if (!parameters.roundtrip && fixed_start) + { + ManipulateTableForNonRoundtripFS(source_id, result_duration_table); + } + else if (!parameters.roundtrip && fixed_end) + { + ManipulateTableForNonRoundtripFE(destination_id, result_duration_table); + } std::vector duration_trip; duration_trip.reserve(number_of_locations); // get an optimized order in which the destinations should be visited - if (number_of_locations < BF_MAX_FEASABLE) + if (number_of_locations < BF_MAX_FEASIBLE) { duration_trip = trip::BruteForceTrip(number_of_locations, result_duration_table); } @@ -251,20 +274,28 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, duration_trip = trip::FarthestInsertionTrip(number_of_locations, result_duration_table); } - // rotate result such that roundtrip starts at node with index 0 - // thist first if covers scenarios: !fixed_end || fixed_start || (fixed_start && fixed_end) if (!fixed_end || fixed_start) { + // rotate result such that trip starts at node with index 0 auto desired_start_index = std::find(std::begin(duration_trip), std::end(duration_trip), 0); BOOST_ASSERT(desired_start_index != std::end(duration_trip)); std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); } - else if (fixed_end && !fixed_start && parameters.roundtrip) - { - auto desired_start_index = + else + { // fixed_end + auto destination_index = std::find(std::begin(duration_trip), std::end(duration_trip), destination_id); - BOOST_ASSERT(desired_start_index != std::end(duration_trip)); - std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); + BOOST_ASSERT(destination_index != std::end(duration_trip)); + if (!parameters.roundtrip) + { + // We want the location after destination to be at the front + std::advance(destination_index, 1); + if (destination_index == std::end(duration_trip)) + { + destination_index = std::begin(duration_trip); + } + } + std::rotate(std::begin(duration_trip), destination_index, std::end(duration_trip)); } // get the route when visiting all destinations in optimized order diff --git a/test/nodejs/trip.js b/test/nodejs/trip.js index f26d97b83..683032b3c 100644 --- a/test/nodejs/trip.js +++ b/test/nodejs/trip.js @@ -262,33 +262,19 @@ test('trip: routes Monaco with null hints', function(assert) { }); test('trip: service combinations that are not implemented', function(assert) { - assert.plan(3); + assert.plan(1); var osrm = new OSRM(data_path); - // fixed start, non-roundtrip + // no fixed start, no fixed end, non-roundtrip var options = { coordinates: two_test_coordinates, - source: 'first', + source: 'any', + destination: 'any', roundtrip: false }; osrm.trip(options, function(err, second) { assert.equal('NotImplemented', err.message); }); - - // fixed start, fixed end, non-roundtrip - options.source = 'any'; - options.destination = 'any'; - osrm.trip(options, function(err, second) { - assert.equal('NotImplemented', err.message); - }); - - // fixed end, non-roundtrip - delete options.source; - options.destination = 'last'; - osrm.trip(options, function(err, second) { - assert.equal('NotImplemented', err.message); - }); - }); test('trip: fixed start and end combinations', function(assert) { @@ -302,16 +288,17 @@ test('trip: fixed start and end combinations', function(assert) { geometries: 'geojson' }; - // fixed start and end, non-roundtrip - osrm.trip(options, function(err, fseTrip) { - assert.ifError(err); - assert.equal(1, fseTrip.trips.length); - var coordinates = fseTrip.trips[0].geometry.coordinates; - assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); - }); + // variations of non roundtrip + var nonRoundtripChecks = function(options) { + osrm.trip(options, function(err, fseTrip) { + assert.ifError(err); + assert.equal(1, fseTrip.trips.length); + var coordinates = fseTrip.trips[0].geometry.coordinates; + assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); + }); + }; // variations of roundtrip - var roundtripChecks = function(options) { osrm.trip(options, function(err, trip) { assert.ifError(err); @@ -319,7 +306,20 @@ test('trip: fixed start and end combinations', function(assert) { var coordinates = trip.trips[0].geometry.coordinates; assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); }); - } + }; + + // fixed start and end, non-roundtrip + nonRoundtripChecks(options); + + // fixed start, non-roundtrip + delete options.destination; + options.source = 'first'; + nonRoundtripChecks(options); + + // fixed end, non-roundtrip + delete options.source; + options.destination = 'last'; + nonRoundtripChecks(options); // roundtrip, source and destination not specified roundtripChecks({coordinates: options.coordinates, geometries: options.geometries}); @@ -327,6 +327,7 @@ test('trip: fixed start and end combinations', function(assert) { // roundtrip, fixed destination options.roundtrip = true; delete options.source; + options.destination = 'last'; roundtripChecks(options); //roundtrip, fixed source diff --git a/unit_tests/library/trip.cpp b/unit_tests/library/trip.cpp index 6eb500e81..52308f2e0 100644 --- a/unit_tests/library/trip.cpp +++ b/unit_tests/library/trip.cpp @@ -362,7 +362,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api) ResetParams(locations, params); params.source = TripParameters::SourceType::First; params.roundtrip = false; - CheckNotImplemented(osrm, params, use_json_only_api); + CheckOk(osrm, params, use_json_only_api); ResetParams(locations, params); params.destination = TripParameters::DestinationType::Any; @@ -372,7 +372,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api) ResetParams(locations, params); params.destination = TripParameters::DestinationType::Last; params.roundtrip = false; - CheckNotImplemented(osrm, params, use_json_only_api); + CheckOk(osrm, params, use_json_only_api); // three parameters set params.source = TripParameters::SourceType::Any; @@ -383,12 +383,12 @@ void test_tfse_illegal_parameters(bool use_json_only_api) params.source = TripParameters::SourceType::Any; params.destination = TripParameters::DestinationType::Last; params.roundtrip = false; - CheckNotImplemented(osrm, params, use_json_only_api); + CheckOk(osrm, params, use_json_only_api); params.source = TripParameters::SourceType::First; params.destination = TripParameters::DestinationType::Any; params.roundtrip = false; - CheckNotImplemented(osrm, params, use_json_only_api); + CheckOk(osrm, params, use_json_only_api); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_old_api) { test_tfse_illegal_parameters(true); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_new_api) { test_tfse_illegal_parameters(false); } From 3cfd0e833405f34474ff73706b4c67758fe4a061 Mon Sep 17 00:00:00 2001 From: Michael Bell Date: Mon, 22 Aug 2022 12:58:16 +0100 Subject: [PATCH 08/12] Complete support for no_entry and no_exit turn restrictions (#5988) The internal representation of turn restrictions expects only one `from` way and only one `to` way. `no_entry` and `no_exit` turn restrictions can have multiple `from` and `to` ways respectively. This means they are not fully supported by OSRM's restriction parser. We complete support for these turn restriction types by parsing all ways and converting a valid restriction with multiple `from`/`to` members into multiple internal restrictions. --- CHANGELOG.md | 1 + features/car/restrictions.feature | 120 ++++++++++++++++++++ include/extractor/restriction_parser.hpp | 2 +- src/extractor/restriction_parser.cpp | 84 +++++++++----- src/extractor/scripting_environment_lua.cpp | 8 +- 5 files changed, 184 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b577c71f..dc873de0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) - Routing: + - FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988) - ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050) # 5.26.0 diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature index da76f4ded..b9c878b00 100644 --- a/features/car/restrictions.feature +++ b/features/car/restrictions.feature @@ -1008,3 +1008,123 @@ Feature: Car - Turn restrictions | from | to | route | | d | x | bd,abc,xa,xa | | d | z | bd,abc,cz,cz | + + + Scenario: Multiple restricted entrances + Given the node map + """ + b + | + a----e----c + | + d + """ + + And the ways + | nodes | + | ae | + | be | + | ce | + | de | + + And the relations + | type | way:from | way:to | node:via | restriction | + | restriction | ae,be | ed | e | no_entry | + + When I route I should get + | from | to | route | + | a | d | ae,ce,ce,de,de | + | b | d | be,ce,ce,de,de | + | c | d | ce,de,de | + + + Scenario: Multiple restricted exits + Given the node map + """ + b + | + a----e----c + | + d + """ + + And the ways + | nodes | + | ae | + | be | + | ce | + | de | + + And the relations + | type | way:from | way:to | node:via | restriction | + | restriction | ae | ce,de | e | no_exit | + + When I route I should get + | from | to | route | + | a | b | ae,be,be | + | a | c | ae,be,be,ce,ce | + | a | d | ae,be,be,de,de | + + + Scenario: Invalid restricted entrances/exits + Given the node map + """ + b + | + a----e----c + | + d + """ + + And the ways + | nodes | + | ae | + | be | + | ce | + | de | + + And the relations + | type | way:from | way:to | node:via | restriction | + | restriction | ae | ce,de | e | no_entry | + | restriction | ae,be | ed | e | no_exit | + + When I route I should get + | from | to | route | + | a | b | ae,be,be | + | a | c | ae,ce,ce | + | a | d | ae,de,de | + | b | d | be,de,de | + | c | d | ce,de,de | + + + Scenario: Invalid multi from/to restrictions + Given the node map + """ + b + | + a----e----c + | + d + """ + + And the ways + | nodes | + | ae | + | be | + | ce | + | de | + + And the relations + | type | way:from | way:to | node:via | restriction | + | restriction | ae,de | ce,de | e | no_right_turn | + | restriction | ae,be | ce,de | e | no_straight_on | + | restriction | ae,be | be,ce | e | only_left_turn | + | restriction | ae,be | ce,de | e | only_straight_on | + + When I route I should get + | from | to | route | + | a | b | ae,be,be | + | a | c | ae,ce,ce | + | a | d | ae,de,de | + | b | d | be,de,de | + | c | d | ce,de,de | diff --git a/include/extractor/restriction_parser.hpp b/include/extractor/restriction_parser.hpp index 33367ae14..585396857 100644 --- a/include/extractor/restriction_parser.hpp +++ b/include/extractor/restriction_parser.hpp @@ -44,7 +44,7 @@ class RestrictionParser RestrictionParser(bool use_turn_restrictions, bool parse_conditionals, std::vector &restrictions); - boost::optional TryParse(const osmium::Relation &relation) const; + std::vector TryParse(const osmium::Relation &relation) const; private: bool ShouldIgnoreRestriction(const std::string &except_tag_string) const; diff --git a/src/extractor/restriction_parser.cpp b/src/extractor/restriction_parser.cpp index c81f4331d..a135214f5 100644 --- a/src/extractor/restriction_parser.cpp +++ b/src/extractor/restriction_parser.cpp @@ -50,13 +50,13 @@ RestrictionParser::RestrictionParser(bool use_turn_restrictions_, * in the corresponding profile. We use it for both namespacing restrictions, as in * restriction:motorcar as well as whitelisting if its in except:motorcar. */ -boost::optional +std::vector RestrictionParser::TryParse(const osmium::Relation &relation) const { // return if turn restrictions should be ignored if (!use_turn_restrictions) { - return boost::none; + return {}; } osmium::tags::KeyFilter filter(false); @@ -85,17 +85,19 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const // if it's not a restriction, continue; if (std::distance(fi_begin, fi_end) == 0) { - return boost::none; + return {}; } // check if the restriction should be ignored const char *except = relation.get_value_by_key("except"); if (except != nullptr && ShouldIgnoreRestriction(except)) { - return boost::none; + return {}; } bool is_only_restriction = false; + bool is_multi_from = false; + bool is_multi_to = false; for (; fi_begin != fi_end; ++fi_begin) { @@ -111,21 +113,26 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const else if (value.find("no_") == 0 && !boost::algorithm::ends_with(value, "_on_red")) { is_only_restriction = false; + if (boost::algorithm::starts_with(value, "no_exit")) + { + is_multi_to = true; + } + else if (boost::algorithm::starts_with(value, "no_entry")) + { + is_multi_from = true; + } } else // unrecognized value type { - return boost::none; + return {}; } } - InputTurnRestriction restriction_container; - restriction_container.is_only = is_only_restriction; - constexpr auto INVALID_OSM_ID = std::numeric_limits::max(); - auto from = INVALID_OSM_ID; + std::vector from_ways; auto via_node = INVALID_OSM_ID; std::vector via_ways; - auto to = INVALID_OSM_ID; + std::vector to_ways; bool is_node_restriction = true; for (const auto &member : relation.members()) @@ -157,11 +164,11 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const 0 == strcmp("via", role)); if (0 == strcmp("from", role)) { - from = static_cast(member.ref()); + from_ways.push_back({static_cast(member.ref())}); } else if (0 == strcmp("to", role)) { - to = static_cast(member.ref()); + to_ways.push_back({static_cast(member.ref())}); } else if (0 == strcmp("via", role)) { @@ -178,6 +185,7 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const } } + std::vector condition; // parse conditional tags if (parse_conditionals) { @@ -199,32 +207,54 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const std::vector hours = util::ParseOpeningHours(p.condition); // found unrecognized condition, continue if (hours.empty()) - return boost::none; + return {}; - restriction_container.condition = std::move(hours); + condition = std::move(hours); } } } - if (from != INVALID_OSM_ID && (via_node != INVALID_OSM_ID || !via_ways.empty()) && - to != INVALID_OSM_ID) + std::vector restriction_containers; + if (!from_ways.empty() && (via_node != INVALID_OSM_ID || !via_ways.empty()) && !to_ways.empty()) { - if (is_node_restriction) + if (from_ways.size() > 1 && !is_multi_from) { - // template struct requires bracket for ID initialisation :( - restriction_container.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}}; + util::Log(logDEBUG) << "Parsed restriction " << relation.id() + << " unexpectedly contains " << from_ways.size() + << " from ways, skipping..."; + return {}; } - else + if (to_ways.size() > 1 && !is_multi_to) { - // template struct requires bracket for ID initialisation :( - restriction_container.node_or_way = InputWayRestriction{{from}, via_ways, {to}}; + util::Log(logDEBUG) << "Parsed restriction " << relation.id() + << " unexpectedly contains " << to_ways.size() + << " to ways, skipping..."; + return {}; + } + // Internally restrictions are represented with one 'from' and one 'to' way. + // Therefore we need to convert a multi from/to restriction into multiple restrictions. + for (const auto &from : from_ways) + { + for (const auto &to : to_ways) + { + InputTurnRestriction restriction; + restriction.is_only = is_only_restriction; + restriction.condition = condition; + if (is_node_restriction) + { + // template struct requires bracket for ID initialisation :( + restriction.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}}; + } + else + { + // template struct requires bracket for ID initialisation :( + restriction.node_or_way = InputWayRestriction{{from}, via_ways, {to}}; + } + restriction_containers.push_back(std::move(restriction)); + } } - return restriction_container; - } - else - { - return boost::none; } + return restriction_containers; } bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp index 2d0978d51..744140022 100644 --- a/src/extractor/scripting_environment_lua.cpp +++ b/src/extractor/scripting_environment_lua.cpp @@ -909,13 +909,15 @@ void Sol2ScriptingEnvironment::ProcessElements( case osmium::item_type::relation: { const auto &relation = static_cast(*entity); - if (auto result_res = restriction_parser.TryParse(relation)) + auto results = restriction_parser.TryParse(relation); + if (!results.empty()) { - resulting_restrictions.push_back(*result_res); + std::move( + results.begin(), results.end(), std::back_inserter(resulting_restrictions)); } else if (auto result_res = maneuver_override_parser.TryParse(relation)) { - resulting_maneuver_overrides.push_back(*result_res); + resulting_maneuver_overrides.push_back(std::move(*result_res)); } } break; From 972a848094e31ee6a13e64a552700d515b6eeca4 Mon Sep 17 00:00:00 2001 From: Michael Bell Date: Mon, 22 Aug 2022 12:59:20 +0100 Subject: [PATCH 09/12] Lazily generate optional route path data (#6045) Currently route results are annotated with additional path information, such as geometries, turn-by-turn steps and other metadata. These annotations are generated if they are not requested or returned in the response. Datasets needed to generate these annotations are loaded and available to the OSRM process even when unused. This commit is a first step towards making the loading of these datasets optional. We refactor the code so that route annotations are only generated if explicitly requested and needed in the response. Specifically, we change the following annotations to be lazily generated: - Turn-by-turn steps - Route Overview geometry - Route segment metadata For example. a /route/v1 request with steps=false&overview=false&annotations=false would no longer call the following data facade methods: - GetOSMNodeIDOfNode - GetTurnInstructionForEdgeID - GetNameIndex - GetNameForID - GetRefForID - GetTurnInstructionForEdgeID - GetClassData - IsLeftHandDriving - GetTravelMode - IsSegregated - PreTurnBearing - PostTurnBearing - HasLaneData - GetLaneData - GetEntryClass Requests that include segment metadata and/or overview geometry but not turn-by-turn instructions will also benefit from this, although there is some interdependency with the step instructions - a call to GetTurnInstructionForEdgeID is still required. Requests for OSM annotations will understandably still need to call GetOSMNodeIDOfNode. Making these changes unlocks the optional loading of data contained in the following OSRM files: - osrm.names - osrm.icd - osrm.nbg_nodes (partial) - osrm.ebg_nodes (partial) - osrm.edges --- CHANGELOG.md | 1 + include/engine/api/route_api.hpp | 162 ++++++++++-------- include/engine/guidance/assemble_geometry.hpp | 20 +-- include/engine/guidance/assemble_leg.hpp | 91 +++++----- include/engine/guidance/assemble_steps.hpp | 64 +++++-- include/engine/guidance/leg_geometry.hpp | 2 +- include/engine/internal_route_result.hpp | 32 +--- .../routing_algorithms/routing_base.hpp | 42 +---- src/engine/guidance/post_processing.cpp | 11 +- src/extractor/edge_based_graph_factory.cpp | 2 +- .../engine/collapse_internal_route_result.cpp | 32 ++-- unit_tests/engine/guidance_assembly.cpp | 4 +- 12 files changed, 231 insertions(+), 232 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc873de0d..31a05486a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) - Routing: + - CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045) - FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988) - ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050) diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 72244c453..7b4dfc02f 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -367,7 +367,7 @@ class RouteAPI : public BaseAPI // To maintain support for uses of the old default constructors, we check // if annotations property was set manually after default construction auto requested_annotations = parameters.annotations_type; - if ((parameters.annotations == true) && + if (parameters.annotations && (parameters.annotations_type == RouteParameters::AnnotationsType::None)) { requested_annotations = RouteParameters::AnnotationsType::All; @@ -497,10 +497,10 @@ class RouteAPI : public BaseAPI std::vector nodes; if (requested_annotations & RouteParameters::AnnotationsType::Nodes) { - nodes.reserve(leg_geometry.osm_node_ids.size()); - for (const auto node_id : leg_geometry.osm_node_ids) + nodes.reserve(leg_geometry.node_ids.size()); + for (const auto node_id : leg_geometry.node_ids) { - nodes.emplace_back(static_cast(node_id)); + nodes.emplace_back(static_cast(facade.GetOSMNodeIDOfNode(node_id))); } } auto nodes_vector = fb_result.CreateVector(nodes); @@ -515,7 +515,7 @@ class RouteAPI : public BaseAPI { const auto name = facade.GetDatasourceName(i); // Length of 0 indicates the first empty name, so we can stop here - if (name.size() == 0) + if (name.empty()) break; names.emplace_back( fb_result.CreateString(std::string(facade.GetDatasourceName(i)))); @@ -763,7 +763,7 @@ class RouteAPI : public BaseAPI // To maintain support for uses of the old default constructors, we check // if annotations property was set manually after default construction auto requested_annotations = parameters.annotations_type; - if ((parameters.annotations == true) && + if (parameters.annotations && (parameters.annotations_type == RouteParameters::AnnotationsType::None)) { requested_annotations = RouteParameters::AnnotationsType::All; @@ -825,10 +825,11 @@ class RouteAPI : public BaseAPI if (requested_annotations & RouteParameters::AnnotationsType::Nodes) { util::json::Array nodes; - nodes.values.reserve(leg_geometry.osm_node_ids.size()); - for (const auto node_id : leg_geometry.osm_node_ids) + nodes.values.reserve(leg_geometry.node_ids.size()); + for (const auto node_id : leg_geometry.node_ids) { - nodes.values.push_back(static_cast(node_id)); + nodes.values.push_back( + static_cast(facade.GetOSMNodeIDOfNode(node_id))); } annotation.values["nodes"] = std::move(nodes); } @@ -842,7 +843,7 @@ class RouteAPI : public BaseAPI { const auto name = facade.GetDatasourceName(i); // Length of 0 indicates the first empty name, so we can stop here - if (name.size() == 0) + if (name.empty()) break; datasource_names.values.push_back(std::string(facade.GetDatasourceName(i))); } @@ -888,81 +889,92 @@ class RouteAPI : public BaseAPI const bool reversed_source = source_traversed_in_reverse[idx]; const bool reversed_target = target_traversed_in_reverse[idx]; - auto leg_geometry = guidance::assembleGeometry(BaseAPI::facade, - path_data, - phantoms.source_phantom, - phantoms.target_phantom, - reversed_source, - reversed_target); auto leg = guidance::assembleLeg(facade, path_data, - leg_geometry, phantoms.source_phantom, phantoms.target_phantom, - reversed_target, - parameters.steps); + reversed_target); - util::Log(logDEBUG) << "Assembling steps " << std::endl; - if (parameters.steps) + guidance::LegGeometry leg_geometry; + + // Generate additional geometry data if request includes turn-by-turn steps, + // overview geometry or route geometry annotations. + // Note that overview geometry and route geometry annotations can return different + // results depending on whether turn-by-turn steps are also requested. + if (parameters.steps || parameters.annotations || + parameters.overview != RouteParameters::OverviewType::False) { - auto steps = guidance::assembleSteps(BaseAPI::facade, - path_data, - leg_geometry, - phantoms.source_phantom, - phantoms.target_phantom, - reversed_source, - reversed_target); - // Apply maneuver overrides before any other post - // processing is performed - guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry); + leg_geometry = guidance::assembleGeometry(BaseAPI::facade, + path_data, + phantoms.source_phantom, + phantoms.target_phantom, + reversed_source, + reversed_target); - // Collapse segregated steps before others - steps = guidance::collapseSegregatedTurnInstructions(std::move(steps)); + util::Log(logDEBUG) << "Assembling steps " << std::endl; + if (parameters.steps) + { + leg.summary = guidance::assembleSummary( + facade, path_data, phantoms.target_phantom, reversed_target); - /* Perform step-based post-processing. - * - * Using post-processing on basis of route-steps for a single leg at a time - * comes at the cost that we cannot count the correct exit for roundabouts. - * We can only emit the exit nr/intersections up to/starting at a part of the leg. - * If a roundabout is not terminated in a leg, we will end up with a - *enter-roundabout - * and exit-roundabout-nr where the exit nr is out of sync with the previous enter. - * - * | S | - * * * - * ----* * ---- - * T - * ----* * ---- - * V * * - * | | - * | | - * - * Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to - *take - * the second exit, even though counting from S it would be the third. - * For S, we only emit `roundabout` without an exit number, showing that we enter a - *roundabout - * to find a via point. - * The same exit will be emitted, though, if we should start routing at S, making - * the overall response consistent. - * - * ⚠ CAUTION: order of post-processing steps is important - * - handleRoundabouts must be called before collapseTurnInstructions that - * expects post-processed roundabouts - */ + auto steps = guidance::assembleSteps(BaseAPI::facade, + path_data, + leg_geometry, + phantoms.source_phantom, + phantoms.target_phantom, + reversed_source, + reversed_target); - guidance::trimShortSegments(steps, leg_geometry); - leg.steps = guidance::handleRoundabouts(std::move(steps)); - leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps)); - leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); - leg.steps = guidance::buildIntersections(std::move(leg.steps)); - leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps)); - leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), - leg_geometry, - phantoms.source_phantom, - phantoms.target_phantom); - leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); + // Apply maneuver overrides before any other post + // processing is performed + guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry); + + // Collapse segregated steps before others + steps = guidance::collapseSegregatedTurnInstructions(std::move(steps)); + + /* Perform step-based post-processing. + * + * Using post-processing on basis of route-steps for a single leg at a time + * comes at the cost that we cannot count the correct exit for roundabouts. + * We can only emit the exit nr/intersections up to/starting at a part of the + *leg. If a roundabout is not terminated in a leg, we will end up with a + *enter-roundabout + * and exit-roundabout-nr where the exit nr is out of sync with the previous + *enter. + * + * | S | + * * * + * ----* * ---- + * T + * ----* * ---- + * V * * + * | | + * | | + * + * Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say + *to take the second exit, even though counting from S it would be the third. + * For S, we only emit `roundabout` without an exit number, showing that we + *enter a roundabout to find a via point. The same exit will be emitted, though, + *if we should start routing at S, making the overall response consistent. + * + * ⚠ CAUTION: order of post-processing steps is important + * - handleRoundabouts must be called before collapseTurnInstructions that + * expects post-processed roundabouts + */ + + guidance::trimShortSegments(steps, leg_geometry); + leg.steps = guidance::handleRoundabouts(std::move(steps)); + leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps)); + leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); + leg.steps = guidance::buildIntersections(std::move(leg.steps)); + leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps)); + leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), + leg_geometry, + phantoms.source_phantom, + phantoms.target_phantom); + leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); + } } leg_geometries.push_back(std::move(leg_geometry)); diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 736c868fd..ad5d6cbd1 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -57,8 +57,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id); - geometry.osm_node_ids.push_back( - facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate))); + geometry.node_ids.push_back(source_geometry(source_segment_start_coordinate)); auto cumulative_distance = 0.; auto current_distance = 0.; @@ -71,7 +70,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, cumulative_distance += current_distance; // all changes to this check have to be matched with assemble_steps - if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + auto turn_instruction = path_point.turn_edge + ? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge) + : osrm::guidance::TurnInstruction::NO_TURN(); + if (turn_instruction.type != osrm::guidance::TurnType::NoTurn) { geometry.segment_distances.push_back(cumulative_distance); geometry.segment_offsets.push_back(geometry.locations.size()); @@ -79,11 +81,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, } prev_coordinate = coordinate; + const auto node_id = path_point.turn_via_node; - const auto osm_node_id = facade.GetOSMNodeIDOfNode(path_point.turn_via_node); - - if (osm_node_id != geometry.osm_node_ids.back() || - path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + if (node_id != geometry.node_ids.back() || + turn_instruction.type != osrm::guidance::TurnType::NoTurn) { geometry.annotations.emplace_back(LegGeometry::Annotation{ current_distance, @@ -99,7 +100,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, facade.GetWeightMultiplier(), path_point.datasource_id}); geometry.locations.push_back(std::move(coordinate)); - geometry.osm_node_ids.push_back(osm_node_id); + geometry.node_ids.push_back(node_id); } } current_distance = @@ -158,8 +159,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto target_segment_end_coordinate = target_node.fwd_segment_position + (reversed_target ? 0 : 1); const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id); - geometry.osm_node_ids.push_back( - facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate))); + geometry.node_ids.push_back(target_geometry(target_segment_end_coordinate)); BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1); BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size()); diff --git a/include/engine/guidance/assemble_leg.hpp b/include/engine/guidance/assemble_leg.hpp index 0a49ae81e..617b317cf 100644 --- a/include/engine/guidance/assemble_leg.hpp +++ b/include/engine/guidance/assemble_leg.hpp @@ -75,10 +75,14 @@ std::array summarizeRoute(const datafacade::BaseDa std::vector segments(route_data.size()); std::uint32_t index = 0; - std::transform( - route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point) { - return NamedSegment{point.duration_until_turn, index++, point.name_id}; - }); + std::transform(route_data.begin(), + route_data.end(), + segments.begin(), + [&index, &facade](const PathData &point) { + return NamedSegment{point.duration_until_turn, + index++, + facade.GetNameIndex(point.from_edge_based_node)}; + }); const auto target_duration = target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration; const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id @@ -124,21 +128,59 @@ std::array summarizeRoute(const datafacade::BaseDa } } // namespace detail +inline std::string assembleSummary(const datafacade::BaseDataFacade &facade, + const std::vector &route_data, + const PhantomNode &target_node, + const bool target_traversed_in_reverse) +{ + auto summary_array = detail::summarizeRoute( + facade, route_data, target_node, target_traversed_in_reverse); + + BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0); + BOOST_ASSERT(summary_array.begin() != summary_array.end()); + + // transform a name_id into a string containing either the name, or -if the name is empty- + // the reference. + const auto name_id_to_string = [&](const NameID name_id) { + const auto name = facade.GetNameForID(name_id); + if (!name.empty()) + return name.to_string(); + else + { + const auto ref = facade.GetRefForID(name_id); + return ref.to_string(); + } + }; + + const auto not_empty = [&](const std::string &name) { return !name.empty(); }; + + const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) | + boost::adaptors::filtered(not_empty); + return boost::algorithm::join(summary_names, ", "); +} + inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, const std::vector &route_data, - const LegGeometry &leg_geometry, const PhantomNode &source_node, const PhantomNode &target_node, - const bool target_traversed_in_reverse, - const bool needs_summary) + const bool target_traversed_in_reverse) { + auto distance = 0.; + auto prev_coordinate = source_node.location; + for (const auto &path_point : route_data) + { + auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node); + distance += util::coordinate_calculation::greatCircleDistance(prev_coordinate, coordinate); + prev_coordinate = coordinate; + } + distance += + util::coordinate_calculation::greatCircleDistance(prev_coordinate, target_node.location); + const auto target_duration = (target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration); const auto target_weight = (target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight); - auto distance = std::accumulate( - leg_geometry.segment_distances.begin(), leg_geometry.segment_distances.end(), 0.); auto duration = std::accumulate( route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) { return sum + data.duration_until_turn; @@ -182,39 +224,10 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, duration = std::max(0, duration); } - std::string summary; - if (needs_summary) - { - auto summary_array = detail::summarizeRoute( - facade, route_data, target_node, target_traversed_in_reverse); - - BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0); - BOOST_ASSERT(summary_array.begin() != summary_array.end()); - - // transform a name_id into a string containing either the name, or -if the name is empty- - // the reference. - const auto name_id_to_string = [&](const NameID name_id) { - const auto name = facade.GetNameForID(name_id); - if (!name.empty()) - return name.to_string(); - else - { - const auto ref = facade.GetRefForID(name_id); - return ref.to_string(); - } - }; - - const auto not_empty = [&](const std::string &name) { return !name.empty(); }; - - const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) | - boost::adaptors::filtered(not_empty); - summary = boost::algorithm::join(summary_names, ", "); - } - return RouteLeg{std::round(distance * 10.) / 10., duration / 10., weight / facade.GetWeightMultiplier(), - summary, + "", {}}; } diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index ac65a539f..97d527c7b 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -19,6 +19,7 @@ #include #include +#include #include namespace osrm @@ -96,7 +97,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa {}, source_classes}; - if (leg_data.size() > 0) + if (!leg_data.empty()) { // PathData saves the information we need of the segment _before_ the turn, // but a RouteStep is with regard to the segment after the turn. @@ -115,7 +116,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa segment_weight += path_point.weight_until_turn; // all changes to this check have to be matched with assemble_geometry - if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + const auto turn_instruction = + path_point.turn_edge ? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge) + : osrm::guidance::TurnInstruction::NO_TURN(); + if (turn_instruction.type != osrm::guidance::TurnType::NoTurn) { BOOST_ASSERT(segment_weight >= 0); const auto name = facade.GetNameForID(step_name_id); @@ -125,7 +129,13 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa const auto exits = facade.GetExitsForID(step_name_id); const auto distance = leg_geometry.segment_distances[segment_index]; // intersections contain the classes of exiting road - intersection.classes = facade.GetClasses(path_point.classes); + intersection.classes = + facade.GetClasses(facade.GetClassData(path_point.from_edge_based_node)); + + const auto is_left_hand_driving = + facade.IsLeftHandDriving(path_point.from_edge_based_node); + const auto travel_mode = facade.GetTravelMode(path_point.from_edge_based_node); + BOOST_ASSERT(travel_mode > 0); steps.push_back(RouteStep{path_point.from_edge_based_node, step_name_id, @@ -140,17 +150,19 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa segment_duration / 10., distance, segment_weight / weight_multiplier, - path_point.travel_mode, + travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1, {intersection}, - path_point.is_left_hand_driving}); + is_left_hand_driving}); 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; + step_name_id = + facade.GetNameIndex(leg_data[leg_data_index + 1].from_edge_based_node); + is_segregated = + facade.IsSegregated(leg_data[leg_data_index + 1].from_edge_based_node); } else { @@ -159,20 +171,33 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa } // extract bearings - bearings = std::make_pair( - path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get()); + auto pre_turn_bearing = path_point.turn_edge + ? facade.PreTurnBearing(*path_point.turn_edge) + : osrm::guidance::TurnBearing(0); + auto post_turn_bearing = path_point.turn_edge + ? facade.PostTurnBearing(*path_point.turn_edge) + : osrm::guidance::TurnBearing(0); + bearings = std::make_pair(pre_turn_bearing.Get(), + post_turn_bearing.Get()); const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node); auto bearing_data = bearing_class.getAvailableBearings(); + + util::guidance::LaneTupleIdPair lane_data = {{0, INVALID_LANEID}, + INVALID_LANE_DESCRIPTIONID}; + if (path_point.turn_edge && facade.HasLaneData(*path_point.turn_edge)) + { + lane_data = facade.GetLaneData(*path_point.turn_edge); + } + intersection.in = bearing_class.findMatchingBearing(bearings.first); intersection.out = bearing_class.findMatchingBearing(bearings.second); intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node); intersection.bearings.clear(); intersection.bearings.reserve(bearing_data.size()); - intersection.lanes = path_point.lane_data.first; - intersection.lane_description = - path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID - ? facade.GetTurnDescription(path_point.lane_data.second) - : extractor::TurnLaneDescription(); + intersection.lanes = lane_data.first; + intersection.lane_description = lane_data.second != INVALID_LANE_DESCRIPTIONID + ? facade.GetTurnDescription(lane_data.second) + : extractor::TurnLaneDescription(); // Lanes in turn are bound by total number of lanes at the location BOOST_ASSERT(intersection.lanes.lanes_in_turn <= @@ -183,20 +208,23 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa (!intersection.lane_description.empty() && intersection.lanes.lanes_in_turn != 0)); + auto entry_class = path_point.turn_edge + ? facade.GetEntryClass(*path_point.turn_edge) + : EMPTY_ENTRY_CLASS; std::copy(bearing_data.begin(), bearing_data.end(), std::back_inserter(intersection.bearings)); intersection.entry.clear(); for (auto idx : util::irange(0, intersection.bearings.size())) { - intersection.entry.push_back(path_point.entry_class.allowsEntry(idx)); + intersection.entry.push_back(entry_class.allowsEntry(idx)); } std::int16_t bearing_in_driving_direction = util::bearing::reverse(std::round(bearings.first)); maneuver = {intersection.location, bearing_in_driving_direction, bearings.second, - path_point.turn_instruction, + turn_instruction, WaypointType::None, 0}; segment_index++; @@ -269,7 +297,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa leg_geometry.segment_distances[segment_index], weight / weight_multiplier, source_mode, - std::move(maneuver), + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1, {intersection}, @@ -312,7 +340,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa ZERO_DISTANCE, ZERO_WEIGHT, target_mode, - std::move(maneuver), + maneuver, leg_geometry.locations.size() - 1, leg_geometry.locations.size(), {intersection}, diff --git a/include/engine/guidance/leg_geometry.hpp b/include/engine/guidance/leg_geometry.hpp index 8374bb992..78ebd42ad 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -32,7 +32,7 @@ struct LegGeometry // length of the segment in meters std::vector segment_distances; // original OSM node IDs for each coordinate - std::vector osm_node_ids; + std::vector node_ids; // Per-coordinate metadata struct Annotation diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index 9f5443ffa..4ee80ab6a 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -15,6 +15,7 @@ #include "util/integer_range.hpp" #include "util/typedefs.hpp" +#include #include namespace osrm @@ -28,43 +29,22 @@ struct PathData NodeID from_edge_based_node; // the internal OSRM id of the OSM node id that is the via node of the turn 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; - // If this segment immediately preceeds a turn, then duration_of_turn + // If this segment immediately precedes a turn, then duration_of_turn // will contain the weight of the turn. Otherwise it will be 0. EdgeWeight weight_of_turn; // duration that is traveled on the segment until the turn is reached, - // including a turn if the segment preceeds one. + // including a turn if the segment precedes one. EdgeWeight duration_until_turn; - // If this segment immediately preceeds a turn, then duration_of_turn + // If this segment immediately precedes a turn, then duration_of_turn // will contain the duration of the turn. Otherwise it will be 0. EdgeWeight duration_of_turn; - // instruction to execute at the turn - osrm::guidance::TurnInstruction turn_instruction; - // turn lane data - util::guidance::LaneTupleIdPair lane_data; - // travel mode of the street that leads to the turn - extractor::TravelMode travel_mode : 4; - // user defined classed of the street that leads to the turn - extractor::ClassData classes; - // entry class of the turn, indicating possibility of turns - util::guidance::EntryClass entry_class; - // Source of the speed value on this road segment DatasourceID datasource_id; - - // bearing (as seen from the intersection) pre-turn - osrm::guidance::TurnBearing pre_turn_bearing; - // bearing (as seen from the intersection) post-turn - osrm::guidance::TurnBearing post_turn_bearing; - - // Driving side of the turn - bool is_left_hand_driving; + // If segment precedes a turn, ID of the turn itself + boost::optional turn_edge; }; struct InternalRouteResult diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index c7df59e80..59a0113fe 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -176,11 +176,6 @@ void annotatePath(const FacadeT &facade, const auto &edge_data = facade.GetEdgeData(*edge); 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); const auto geometry_index = facade.GetGeometryIndex(node_id); get_segment_geometry(geometry_index); @@ -206,45 +201,29 @@ void annotatePath(const FacadeT &facade, } const std::size_t end_index = weight_vector.size(); - bool is_left_hand_driving = facade.IsLeftHandDriving(node_id); - 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{*node_from, + PathData{node_id, id_vector[segment_idx + 1], - name_index, - is_segregated, static_cast(weight_vector[segment_idx]), 0, static_cast(duration_vector[segment_idx]), 0, - guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - travel_mode, - classes, - EMPTY_ENTRY_CLASS, datasource_vector[segment_idx], - osrm::guidance::TurnBearing(0), - osrm::guidance::TurnBearing(0), - is_left_hand_driving}); + boost::none}); } BOOST_ASSERT(unpacked_path.size() > 0); - if (facade.HasLaneData(turn_id)) - unpacked_path.back().lane_data = facade.GetLaneData(turn_id); const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id); const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id); - unpacked_path.back().entry_class = facade.GetEntryClass(turn_id); - unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().duration_until_turn += turn_duration; unpacked_path.back().duration_of_turn = turn_duration; unpacked_path.back().weight_until_turn += turn_weight; unpacked_path.back().weight_of_turn = turn_weight; - unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id); - unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id); + unpacked_path.back().turn_edge = turn_id; } std::size_t start_index = 0, end_index = 0; @@ -280,33 +259,22 @@ 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)) { BOOST_ASSERT(segment_idx < static_cast(id_vector.size() - 1)); - BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0); unpacked_path.push_back( PathData{target_node_id, id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], - facade.GetNameIndex(target_node_id), - facade.IsSegregated(target_node_id), static_cast(weight_vector[segment_idx]), 0, static_cast(duration_vector[segment_idx]), 0, - guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - facade.GetTravelMode(target_node_id), - facade.GetClassData(target_node_id), - EMPTY_ENTRY_CLASS, datasource_vector[segment_idx], - guidance::TurnBearing(0), - guidance::TurnBearing(0), - is_target_left_hand_driving}); + boost::none}); } - if (unpacked_path.size() > 0) + if (!unpacked_path.empty()) { const auto source_weight = start_traversed_in_reverse ? phantom_node_pair.source_phantom.reverse_weight diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index f510e04b0..ac73e75b7 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -279,8 +279,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.begin() + offset); geometry.annotations.erase(geometry.annotations.begin(), geometry.annotations.begin() + offset); - geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(), - geometry.osm_node_ids.begin() + offset); + geometry.node_ids.erase(geometry.node_ids.begin(), geometry.node_ids.begin() + offset); } auto const first_bearing = steps.front().maneuver.bearing_after; @@ -377,7 +376,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // remove all the last coordinates from the geometry geometry.locations.resize(geometry.segment_offsets.back() + 1); geometry.annotations.resize(geometry.segment_offsets.back()); - geometry.osm_node_ids.resize(geometry.segment_offsets.back() + 1); + geometry.node_ids.resize(geometry.segment_offsets.back() + 1); BOOST_ASSERT(geometry.segment_distances.back() <= 1); geometry.segment_distances.pop_back(); @@ -414,7 +413,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // This can happen if the last coordinate snaps to a node in the unpacked geometry geometry.locations.pop_back(); geometry.annotations.pop_back(); - geometry.osm_node_ids.pop_back(); + geometry.node_ids.pop_back(); geometry.segment_offsets.back()--; // since the last geometry includes the location of arrival, the arrival instruction // geometry overlaps with the previous segment @@ -436,7 +435,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) } BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.locations.size()); - BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.osm_node_ids.size()); + BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.node_ids.size()); BOOST_ASSERT(geometry.segment_offsets.back() == geometry.annotations.size()); BOOST_ASSERT(steps.back().geometry_end == geometry.locations.size()); @@ -541,7 +540,7 @@ std::vector buildIntersections(std::vector steps) { // End of road is a turn that helps to identify the location of a turn. If the turn does - // not pass by any oter intersections, the end-of-road characteristic does not improve + // not pass by any other intersections, the end-of-road characteristic does not improve // the instructions. // Here we reduce the verbosity of our output by reducing end-of-road emissions in cases // where no intersections have been passed in between. diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index edef3d589..b1f94a7b6 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -71,7 +71,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( const extractor::LaneDescriptionMap &lane_description_map) : m_edge_based_node_container(node_data_container), m_connectivity_checksum(0), 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_node_based_graph(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) diff --git a/unit_tests/engine/collapse_internal_route_result.cpp b/unit_tests/engine/collapse_internal_route_result.cpp index fc989ba57..c14fa3967 100644 --- a/unit_tests/engine/collapse_internal_route_result.cpp +++ b/unit_tests/engine/collapse_internal_route_result.cpp @@ -19,8 +19,8 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result) PhantomNode target; source.forward_segment_id = {1, true}; target.forward_segment_id = {6, true}; - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; InternalRouteResult one_leg_result; one_leg_result.unpacked_path_segments = {{pathy, kathy}}; one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}}; @@ -37,13 +37,11 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result) BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) { - // from_edge_based_node, turn_via_node, name_id, is_segregated, weight_until_turn, - // weight_of_turn, - // duration_until_turn, duration_of_turn, turn_instruction, lane_data, travel_mode, classes, - // entry_class, datasource_id, pre_turn_bearing, post_turn_bearing, left_hand - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + // from_edge_based_node, turn_via_node, weight_until_turn, weight_of_turn, + // duration_until_turn, duration_of_turn, datasource_id, turn_edge + PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -73,11 +71,11 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData qathy{0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData mathy{0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; + PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData qathy{0, 5, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; + PathData mathy{0, 4, 8, 9, 13, 4, 2, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -117,9 +115,9 @@ BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) BOOST_AUTO_TEST_CASE(two_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; diff --git a/unit_tests/engine/guidance_assembly.cpp b/unit_tests/engine/guidance_assembly.cpp index 2560fb046..10ba1821d 100644 --- a/unit_tests/engine/guidance_assembly.cpp +++ b/unit_tests/engine/guidance_assembly.cpp @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments) {FloatLongitude{-73.981495}, FloatLatitude{40.768275}}}; geometry.segment_offsets = {0, 2}; geometry.segment_distances = {1.9076601161280742}; - geometry.osm_node_ids = {OSMNodeID{0}, OSMNodeID{1}, OSMNodeID{2}}; + geometry.node_ids = {NodeID{0}, NodeID{1}, NodeID{2}}; geometry.annotations = {{1.9076601161280742, 0.2, 0.2, 0}, {0, 0, 0, 0}}; trimShortSegments(steps, geometry); @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments) BOOST_CHECK_EQUAL(geometry.segment_offsets.back(), 1); BOOST_CHECK_EQUAL(geometry.annotations.size(), 1); BOOST_CHECK_EQUAL(geometry.locations.size(), 2); - BOOST_CHECK_EQUAL(geometry.osm_node_ids.size(), 2); + BOOST_CHECK_EQUAL(geometry.node_ids.size(), 2); } BOOST_AUTO_TEST_SUITE_END() From 928867c520acf07ac6bba9db2163f4200ee283f9 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Mon, 22 Aug 2022 22:07:32 +0300 Subject: [PATCH 10/12] Add `data_version` field to responses of all plugins. (#5387) --- .github/workflows/osrm-backend.yml | 4 +- CHANGELOG.md | 1 + features/nearest/pick.feature | 52 ++++++++++++++++++++++++ features/step_definitions/matching.js | 4 ++ features/step_definitions/nearest.js | 6 +++ features/step_definitions/trip.js | 4 ++ features/testbot/distance_matrix.feature | 3 +- features/testbot/matching.feature | 26 ++++++++++-- features/testbot/snap.feature | 32 ++++++++++++--- features/testbot/trip.feature | 48 +++++++++++++++++++--- include/engine/api/match_api.hpp | 5 +++ include/engine/api/nearest_api.hpp | 5 +++ include/engine/api/table_api.hpp | 5 +++ include/engine/api/trip_api.hpp | 5 +++ 14 files changed, 183 insertions(+), 17 deletions(-) diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index 4addd0564..e25a97528 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -469,9 +469,9 @@ jobs: uses: actions/cache@v2 with: path: ${{github.workspace}}/test/cache - key: v2-test-${{ matrix.name }}-${{ github.sha }} + key: v3-test-${{ matrix.name }}-${{ github.sha }} restore-keys: | - v2-test-${{ matrix.name }}- + v3-test-${{ matrix.name }}- - name: Prepare environment run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 31a05486a..61996ca23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - Changes from 5.26.0 - API: + - CHANGED: Add `data_version` field to responses of all services. [#5387](https://github.com/Project-OSRM/osrm-backend/pull/5387) - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - Misc: diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature index fb66ef654..dcdf5268c 100644 --- a/features/nearest/pick.feature +++ b/features/nearest/pick.feature @@ -59,6 +59,31 @@ Feature: Locating Nearest node on a Way - pick closest way | 3 | u | | 4 | w | + Scenario: Nearest - inside a oneway triangle + Given the node map + """ + c + + y z + 0 1 + 2 3 4 + a x u w b + """ + + And the ways + | nodes | oneway | + | ab | yes | + | bc | yes | + | ca | yes | + + When I request nearest I should get + | in | out | + | 0 | y | + | 1 | z | + | 2 | x | + | 3 | u | + | 4 | w | + Scenario: Nearest - High lat/lon Given the node locations | node | lat | lon | @@ -78,3 +103,30 @@ Feature: Locating Nearest node on a Way - pick closest way | x | a | | y | b | | z | c | + + Scenario: Nearest - data version + Given the node map + """ + c + + y z + 0 1 + 2 3 4 + a x u w b + """ + + And the ways + | nodes | + | ab | + | bc | + | ca | + + And the extract extra arguments "--data_version cucumber_data_version" + + When I request nearest I should get + | in | out | data_version | + | 0 | y | cucumber_data_version | + | 1 | z | cucumber_data_version | + | 2 | x | cucumber_data_version | + | 3 | u | cucumber_data_version | + | 4 | w | cucumber_data_version | diff --git a/features/step_definitions/matching.js b/features/step_definitions/matching.js index d7c62ee07..c8afa5838 100644 --- a/features/step_definitions/matching.js +++ b/features/step_definitions/matching.js @@ -117,6 +117,10 @@ module.exports = function () { got.duration = duration.toString(); } + if (headers.has('data_version')) { + got.data_version = json.data_version || ''; + } + // if header matches 'a:*', parse out the values for * // and return in that header headers.forEach((k) => { diff --git a/features/step_definitions/nearest.js b/features/step_definitions/nearest.js index ae4079b8d..49ec0775d 100644 --- a/features/step_definitions/nearest.js +++ b/features/step_definitions/nearest.js @@ -8,6 +8,7 @@ module.exports = function () { this.reprocessAndLoadData((e) => { if (e) return callback(e); var testRow = (row, ri, cb) => { + var inNode = this.findNodeByName(row.in); if (!inNode) throw new Error(util.format('*** unknown in-node "%s"', row.in)); @@ -17,6 +18,7 @@ module.exports = function () { this.requestNearest(inNode, this.queryParams, (err, response) => { if (err) return cb(err); var coord; + var headers = new Set(table.raw()[0]); if (response.statusCode === 200 && response.body.length) { var json = JSON.parse(response.body); @@ -25,6 +27,10 @@ module.exports = function () { var got = { in: row.in, out: row.out }; + if (headers.has('data_version')) { + got.data_version = json.data_version || ''; + } + Object.keys(row).forEach((key) => { if (key === 'out') { if (this.FuzzyMatch.matchLocation(coord, outNode)) { diff --git a/features/step_definitions/trip.js b/features/step_definitions/trip.js index ab2f7c35e..0efbc2259 100644 --- a/features/step_definitions/trip.js +++ b/features/step_definitions/trip.js @@ -43,6 +43,10 @@ module.exports = function () { got.message = json.message; } + if (headers.has('data_version')) { + got.data_version = json.data_version || ''; + } + if (headers.has('geometry')) { if (this.queryParams['geometries'] === 'polyline') { got.geometry = polyline.decode(json.trips[0].geometry).toString(); diff --git a/features/testbot/distance_matrix.feature b/features/testbot/distance_matrix.feature index c1340146f..92f4b8a6a 100644 --- a/features/testbot/distance_matrix.feature +++ b/features/testbot/distance_matrix.feature @@ -726,4 +726,5 @@ Feature: Basic Distance Matrix | | 1 | 2 | 3 | | 1 | 0 | 1000.1 | 1400.1 | | 2 | 1000.1 | 0 | 400 | - | 3 | 1400.1 | 400 | 0 | \ No newline at end of file + | 3 | 1400.1 | 400 | 0 | + diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature index f8e1b2738..2772ef03a 100644 --- a/features/testbot/matching.feature +++ b/features/testbot/matching.feature @@ -21,8 +21,27 @@ Feature: Basic Map Matching | abcd | no | When I match I should get - | trace | timestamps | matchings | - | ab1d | 0 1 2 3 | ad | + | trace | timestamps | matchings | data_version | + | ab1d | 0 1 2 3 | ad | | + + Scenario: Data_version test on matching + Given a grid size of 100 meters + Given the node map + """ + a b c d + + 1 + """ + + And the extract extra arguments "--data_version cucumber_data_version" + + And the ways + | nodes | oneway | + | abcd | no | + + When I match I should get + | trace | timestamps | matchings | data_version | + | ab1d | 0 1 2 3 | ad | cucumber_data_version | Scenario: Testbot - Map matching with trace splitting Given the node map @@ -792,4 +811,5 @@ Feature: Basic Map Matching When I match I should get | trace | geometry | a:distance | a:duration | a:weight | duration | | 2345 | 1.00018,1,1.000314,1 | 14.914666 | 1.4 | 1.4 | 1.4 | - | 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 | \ No newline at end of file + | 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 | + diff --git a/features/testbot/snap.feature b/features/testbot/snap.feature index 924e84f75..f9a6fff81 100644 --- a/features/testbot/snap.feature +++ b/features/testbot/snap.feature @@ -47,11 +47,31 @@ Feature: Snap start/end point to the nearest way | adb | When I route I should get - | from | to | route | - | 1 | b | adb,adb | - | 2 | b | adb,adb | - | 6 | b | aub,aub | - | 7 | b | aub,aub | + | from | to | route | data_version | + | 1 | b | adb,adb | | + | 2 | b | adb,adb | | + | 6 | b | aub,aub | | + | 7 | b | aub,aub | | + + Scenario: Data_version check on nearest + Given the node map + """ + 4 5 6 7 + 3 a u + 2 + 1 d b + """ + + And the extract extra arguments "--data_version cucumber_data_version" + + And the ways + | nodes | + | aub | + | adb | + + When I route I should get + | from | to | route | data_version | + | 1 | b | adb,adb | cucumber_data_version | Scenario: Snap to edge right under start/end point Given the node map @@ -182,4 +202,4 @@ Feature: Snap start/end point to the nearest way | x | m | xe,xe | | x | n | xf,xf | | x | o | xg,xg | - | x | p | xh,xh | \ No newline at end of file + | x | p | xh,xh | diff --git a/features/testbot/trip.feature b/features/testbot/trip.feature index 840aadb9c..531ccaa48 100644 --- a/features/testbot/trip.feature +++ b/features/testbot/trip.feature @@ -5,6 +5,24 @@ Feature: Basic trip planning Given the profile "testbot" Given a grid size of 10 meters + Scenario: Testbot - Trip: Invalid options (like was in test suite for a long time) + Given the node map + """ + a b + c d + """ + + And the ways + | nodes | + | ab | + | bc | + | cb | + | da | + + When I plan a trip I should get + | waypoints | trips | code | + | a | | InvalidOptions | + Scenario: Testbot - Trip: Roundtrip between same waypoint Given the node map """ @@ -20,8 +38,28 @@ Feature: Basic trip planning | da | When I plan a trip I should get - | waypoints | trips | - | a,a | aa | + | waypoints | trips | code | + | a,a | aa | Ok | + + Scenario: Testbot - Trip: data version check + Given the node map + """ + a b + c d + """ + + And the ways + | nodes | + | ab | + | bc | + | cb | + | da | + + And the extract extra arguments "--data_version cucumber_data_version" + + When I plan a trip I should get + | waypoints | trips | data_version | code | + | a,a | aa | cucumber_data_version | Ok | Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10) Given the node map @@ -38,9 +76,9 @@ Feature: Basic trip planning | da | When I plan a trip I should get - | waypoints | trips | durations | - | a,b,c,d | abcda | 7.6 | - | d,b,c,a | dbcad | 7.6 | + | waypoints | trips | durations | code | + | a,b,c,d | abcda | 7.6 | Ok | + | d,b,c,a | dbcad | 7.6 | Ok | Scenario: Testbot - Trip: Roundtrip waypoints (more than 10) Given the node map diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index a93e49710..e95882f46 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -89,6 +89,11 @@ class MatchAPI final : public RouteAPI } response.values["matchings"] = std::move(routes); response.values["code"] = "Ok"; + auto data_timestamp = facade.GetTimestamp(); + if (!data_timestamp.empty()) + { + response.values["data_version"] = data_timestamp; + } } protected: diff --git a/include/engine/api/nearest_api.hpp b/include/engine/api/nearest_api.hpp index aff3c57dc..246cfe88c 100644 --- a/include/engine/api/nearest_api.hpp +++ b/include/engine/api/nearest_api.hpp @@ -116,6 +116,11 @@ class NearestAPI final : public BaseAPI } response.values["code"] = "Ok"; + auto data_timestamp = facade.GetTimestamp(); + if (!data_timestamp.empty()) + { + response.values["data_version"] = data_timestamp; + } } const NearestParameters ¶meters; diff --git a/include/engine/api/table_api.hpp b/include/engine/api/table_api.hpp index 72cdea4e6..2c378e6e7 100644 --- a/include/engine/api/table_api.hpp +++ b/include/engine/api/table_api.hpp @@ -226,6 +226,11 @@ class TableAPI final : public BaseAPI } response.values["code"] = "Ok"; + auto data_timestamp = facade.GetTimestamp(); + if (!data_timestamp.empty()) + { + response.values["data_version"] = data_timestamp; + } } protected: diff --git a/include/engine/api/trip_api.hpp b/include/engine/api/trip_api.hpp index 90e5e1391..9b82a016e 100644 --- a/include/engine/api/trip_api.hpp +++ b/include/engine/api/trip_api.hpp @@ -87,6 +87,11 @@ class TripAPI final : public RouteAPI } response.values["trips"] = std::move(routes); response.values["code"] = "Ok"; + auto data_timestamp = facade.GetTimestamp(); + if (!data_timestamp.empty()) + { + response.values["data_version"] = data_timestamp; + } } protected: From 32fb8607e4e0ef145819f876d9a55dcaab5e30f6 Mon Sep 17 00:00:00 2001 From: Maciej Bukczynski Date: Mon, 22 Aug 2022 12:47:47 -0700 Subject: [PATCH 11/12] Add node_osrm support for skip_waypoints parameter (#6060) --- CHANGELOG.md | 2 ++ include/nodejs/node_osrm_support.hpp | 16 ++++++++++++++++ test/nodejs/table.js | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61996ca23..4f6348acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - CHANGED: Add `data_version` field to responses of all services. [#5387](https://github.com/Project-OSRM/osrm-backend/pull/5387) - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) + - NodeJS: + - FIXED: Support `skip_waypoints` in Node bindings [#6060](https://github.com/Project-OSRM/osrm-backend/pull/6060) - Misc: - CHANGED: missing files list is included in exception message. [#5360](https://github.com/Project-OSRM/osrm-backend/pull/5360) - CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318) diff --git a/include/nodejs/node_osrm_support.hpp b/include/nodejs/node_osrm_support.hpp index 400d420a5..25f96661d 100644 --- a/include/nodejs/node_osrm_support.hpp +++ b/include/nodejs/node_osrm_support.hpp @@ -675,6 +675,22 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo &arg params->generate_hints = Nan::To(generate_hints).FromJust(); } + if (Nan::Has(obj, Nan::New("skip_waypoints").ToLocalChecked()).FromJust()) + { + v8::Local skip_waypoints = + Nan::Get(obj, Nan::New("skip_waypoints").ToLocalChecked()).ToLocalChecked(); + if (skip_waypoints.IsEmpty()) + return false; + + if (!skip_waypoints->IsBoolean()) + { + Nan::ThrowError("skip_waypoints must be of type Boolean"); + return false; + } + + params->skip_waypoints = Nan::To(skip_waypoints).FromJust(); + } + if (Nan::Has(obj, Nan::New("exclude").ToLocalChecked()).FromJust()) { v8::Local exclude = diff --git a/test/nodejs/table.js b/test/nodejs/table.js index f4f0e6312..d2c50d83f 100644 --- a/test/nodejs/table.js +++ b/test/nodejs/table.js @@ -130,7 +130,7 @@ tables.forEach(function(annotation) { }); test('table: ' + annotation + ' throws on invalid arguments', function(assert) { - assert.plan(17); + assert.plan(18); var osrm = new OSRM(data_path); var options = {annotations: [annotation.slice(0,-1)]}; assert.throws(function() { osrm.table(options); }, @@ -190,6 +190,8 @@ tables.forEach(function(annotation) { assert.throws(function() { osrm.route({coordinates: two_test_coordinates, generate_hints: null}, function(err, route) {}) }, /generate_hints must be of type Boolean/); + assert.throws(function() { osrm.route({coordinates: two_test_coordinates, skip_waypoints: null}, function(err, route) {}) }, + /skip_waypoints must be of type Boolean/); }); test('table: throws on invalid arguments', function(assert) { @@ -239,6 +241,20 @@ tables.forEach(function(annotation) { }); }); + test('table: ' + annotation + ' table in Monaco without waypoints', function(assert) { + assert.plan(2); + var osrm = new OSRM(data_path); + var options = { + coordinates: two_test_coordinates, + skip_waypoints: true, // false is default + annotations: [annotation.slice(0,-1)] + }; + osrm.table(options, function(err, table) { + assert.strictEqual(table.sources, undefined); + assert.strictEqual(table.destinations, undefined); + }); + }); + test('table: ' + annotation + ' table in Monaco without motorways', function(assert) { assert.plan(2); var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'}); From 869b3fae8255f72bd310e814b88eb332aa019199 Mon Sep 17 00:00:00 2001 From: Michael Bell Date: Mon, 22 Aug 2022 20:55:28 +0100 Subject: [PATCH 12/12] Bump CI complete job to ubuntu-22.04 (#6323) 18.04 is being deprecated. --- .github/workflows/osrm-backend.yml | 10 +++++----- CHANGELOG.md | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index e25a97528..c93d3f411 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -68,12 +68,12 @@ jobs: ./scripts/format.sh && ./scripts/error_on_dirty.sh node ./scripts/validate_changelog.js npm run docs && ./scripts/error_on_dirty.sh - + docker-image: needs: format-taginfo-docs runs-on: ubuntu-22.04 continue-on-error: false - steps: + steps: - name: Check out the repo uses: actions/checkout@v3 - name: Enable osm.pbf cache @@ -85,7 +85,7 @@ jobs: v1-berlin-osm-pbf - name: Docker build run: | - docker build -t osrm-backend-local -f docker/Dockerfile . + docker build -t osrm-backend-local -f docker/Dockerfile . - name: Test Docker image run: | if [ ! -f "${PWD}/berlin-latest.osm.pbf" ]; then @@ -428,7 +428,7 @@ jobs: CXXCOMPILER: ${{ matrix.CXXCOMPILER }} CXXFLAGS: ${{ matrix.CXXFLAGS }} ENABLE_ASSERTIONS: ${{ matrix.ENABLE_ASSERTIONS }} - ENABLE_CLANG_TIDY: ${{ matrix.ENABLE_CLANG_TIDY }} + ENABLE_CLANG_TIDY: ${{ matrix.ENABLE_CLANG_TIDY }} ENABLE_COVERAGE: ${{ matrix.ENABLE_COVERAGE }} ENABLE_GLIBC_WORKAROUND: ${{ matrix.ENABLE_GLIBC_WORKAROUND }} ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }} @@ -659,7 +659,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} ci-complete: - runs-on: ubuntu-18.04 + runs-on: ubuntu-22.04 needs: [build-test-publish, docker-image, windows] steps: - run: echo "CI complete" diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f6348acc..bd078ad78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ - FIXED: Fixed Node docs generation check in CI. [#6058](https://github.com/Project-OSRM/osrm-backend/pull/6058) - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) + - FIXED: Bump CI complete meta job to ubuntu-20.04 [#6323](https://github.com/Project-OSRM/osrm-backend/pull/6323) - Routing: - CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045) - FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988)