Fix distance calculation consistency. (#6315)
Consolidate great circle distance calculations to use cheap ruler library.
This commit is contained in:
		
							parent
							
								
									8f0cd5cf7b
								
							
						
					
					
						commit
						aadc088084
					
				
							
								
								
									
										4
									
								
								.github/workflows/osrm-backend.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/osrm-backend.yml
									
									
									
									
										vendored
									
									
								
							| @ -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: | | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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") | ||||
|  | ||||
| @ -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        | | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -8,26 +8,26 @@ 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  | | ||||
|         | path     |         | 59.9 s | | ||||
|         | track    |         | 60 s   | | ||||
|         | track    | asphalt | 60 s   | | ||||
|         | path     | asphalt | 60 s   | | ||||
|  | ||||
| @ -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| | ||||
| 
 | ||||
|  | ||||
| @ -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       | | ||||
|  | ||||
| @ -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      | | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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       | | ||||
|  | ||||
| @ -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 | | ||||
|             | 1 | 59.1 | 35.2 | | ||||
|             | b | 35   | 11.1 | | ||||
| @ -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 | | ||||
|  | ||||
| @ -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 | | ||||
|  | ||||
| @ -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 | | ||||
|  | ||||
| @ -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 | ||||
| @ -391,14 +391,14 @@ Feature: Turn Lane Guidance | ||||
| 
 | ||||
|           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 | | ||||
|                | 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 | ||||
| @ -812,8 +812,8 @@ Feature: Turn Lane Guidance | ||||
| 
 | ||||
|         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, | | ||||
|             | 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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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                | | ||||
| 
 | ||||
|  | ||||
| @ -161,7 +161,7 @@ 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,c       | ab,bc    | depart,arrive                  | | ||||
| 
 | ||||
|     Scenario: Fork Slight Ramp | ||||
|         Given the node map | ||||
| @ -180,7 +180,7 @@ 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,c       | ab,bc    | depart,arrive                         | | ||||
| 
 | ||||
|     Scenario: Fork Slight Ramp on Through Street | ||||
|         Given the node map | ||||
|  | ||||
| @ -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   | | ||||
|  | ||||
| @ -837,8 +837,8 @@ Feature: Turn Lane Guidance | ||||
| 
 | ||||
|         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,,  | | ||||
|             | 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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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) => { | ||||
|  | ||||
| @ -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   | | ||||
|  | ||||
| @ -109,11 +109,11 @@ Feature: Bearing parameter | ||||
| 
 | ||||
|         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 | 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      | 0->90,90->180,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,ring      | 0->180,180->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,ring           | 0->270,270->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                           | | ||||
|  | ||||
| @ -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 | | ||||
|  | ||||
| @ -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  | | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
| @ -716,10 +717,13 @@ Feature: Basic Distance Matrix | ||||
| 
 | ||||
|         When I route I should get | ||||
|             | from | to | route              | distance   | | ||||
|             | 1    | 2  | abcdef,fghij,fghij | 999.9m  | | ||||
|             | 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      | | ||||
|             |   |   1    | 2      | 3      |    | ||||
|             | 1 |   0    | 1000.1 | 1400.1 | | ||||
|             | 2 | 1000.1 | 0      | 400    | | ||||
|             | 3 | 1400.1 | 400    | 0      | | ||||
| @ -447,14 +447,14 @@ Feature: Basic Duration Matrix | ||||
| 
 | ||||
|         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 | 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 | ||||
| @ -544,20 +544,20 @@ Feature: Basic Duration Matrix | ||||
| 
 | ||||
|         When I request a travel time matrix I should get | ||||
|             |   | a    | b  | f    | 1  | | ||||
|             | a | 0  | 30 | 18 | 30 | | ||||
|             | a | 0    | 30 | 17.9 | 30 | | ||||
|             | b | 30   | 0  | 12   | 24 | | ||||
|             | f | 18 | 12 | 0  | 30 | | ||||
|             | 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 | 0  | 30 | 17.9 | 30 | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get | ||||
|             |   | a    | | ||||
|             | a | 0    | | ||||
|             | b | 30   | | ||||
|             | f | 18 | | ||||
|             | f | 17.9 | | ||||
|             | 1 | 30   | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get estimates for | ||||
| @ -597,20 +597,20 @@ Feature: Basic Duration Matrix | ||||
| 
 | ||||
|         When I request a travel time matrix I should get | ||||
|             |   | a    | b  | f    | 1  | | ||||
|             | a | 0  | 30 | 18 | 30 | | ||||
|             | a | 0    | 30 | 17.9 | 30 | | ||||
|             | b | 30   | 0  | 12   | 24 | | ||||
|             | f | 18 | 12 | 0  | 30 | | ||||
|             | 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 | 0  | 30 | 17.9 | 30 | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get | ||||
|             |   | a    | | ||||
|             | a | 0    | | ||||
|             | b | 30   | | ||||
|             | f | 18 | | ||||
|             | f | 17.9 | | ||||
|             | 1 | 30   | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get estimates for | ||||
| @ -651,21 +651,21 @@ Feature: Basic Duration Matrix | ||||
| 
 | ||||
|         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 | 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 | 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 | | ||||
|             | f | 17.9 | | ||||
|             | 1 | 23.9 | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get estimates for | ||||
|             |   | a | b | f | 1 | | ||||
| @ -720,21 +720,21 @@ Feature: Basic Duration Matrix | ||||
| 
 | ||||
|         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 | 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 | 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 | | ||||
|             | f | 35.8 | | ||||
|             | 1 | 47.8 | | ||||
| 
 | ||||
|         When I request a travel time matrix I should get estimates for | ||||
|             |   | a | b | f | 1 | | ||||
|  | ||||
| @ -280,7 +280,7 @@ Feature: Basic Map Matching | ||||
| 
 | ||||
|         When I match I should get | ||||
|             | trace | matchings | geometry                                           | | ||||
|             | efbc  | efbc      | 1,0.99964,1.00036,0.99964,1.00036,1,1.000719,1 | | ||||
|             | 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 | ||||
| @ -683,7 +683,7 @@ Feature: Basic Map Matching | ||||
|           | overview  | full | | ||||
|         When I match I should get | ||||
|           | trace | geometry                                       | code | | ||||
|           | bgkj  | 1.000135,1,1.000135,0.99964,1.000387,0.999137 | Ok   | | ||||
|           | bgkj  | 1.000135,1,1.000135,0.999638,1.000386,0.999132 | Ok   | | ||||
| 
 | ||||
| 
 | ||||
|     @match @testbot | ||||
| @ -713,11 +713,11 @@ Feature: Basic Map Matching | ||||
|           | 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   | | ||||
|           | 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) | ||||
| @ -741,8 +741,8 @@ Feature: Basic Map Matching | ||||
|           | 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      | | ||||
|           | 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) | ||||
| @ -766,8 +766,8 @@ Feature: Basic Map Matching | ||||
|           | 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      | | ||||
|           | 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      | | ||||
|           | 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      | | ||||
| @ -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 | ||||
|  | ||||
| @ -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  |             |          | | ||||
|  | ||||
| @ -27,7 +27,7 @@ Feature: Distance calculation | ||||
| 
 | ||||
|         When I route I should get | ||||
|             | from | to | route | distance         | | ||||
|             | c    | d  | cd,cd | 6028844m ~4.5% | | ||||
|             | c    | d  | cd,cd | 6310675.7m ~4.5% | | ||||
| 
 | ||||
|     Scenario: Approximated Longitudinal distances at latitude 80 | ||||
|         Given the node locations | ||||
| @ -55,7 +55,7 @@ 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% | | ||||
| 
 | ||||
|     Scenario: Approximated Latitudinal distances at longitude 45 | ||||
|         Given the node locations | ||||
| @ -69,7 +69,7 @@ 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% | | ||||
| 
 | ||||
|     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% | | ||||
|  | ||||
| @ -24,12 +24,12 @@ 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 | | ||||
|             | 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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -29,11 +29,11 @@ Feature: Weight tests | ||||
| 
 | ||||
|         When I route I should get | ||||
|             | waypoints | route   | a:weight    | | ||||
|             | s,t       | abc,cde | 1.1:2:2:1 | | ||||
|             | 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 | ||||
| @ -174,12 +174,12 @@ Feature: Weight tests | ||||
| 
 | ||||
|         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 | | ||||
|             | 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 | ||||
| @ -376,9 +376,9 @@ Feature: Weight tests | ||||
| 
 | ||||
|         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 | | ||||
|             | 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. | ||||
| @ -411,4 +411,4 @@ Feature: Weight tests | ||||
| 
 | ||||
|         When I route I should get | ||||
|             | waypoints | route     | distance | weights  | times    | | ||||
|             | a,b       | acdb,acdb  | 78.3m    | 11.744,0      | 56.4s,0s  | | ||||
|             | a,b       | acdb,acdb | 78.3m    | 11.742,0 | 56.4s,0s | | ||||
|  | ||||
| @ -56,7 +56,7 @@ class BaseAPI | ||||
|             // TODO: check forward/reverse
 | ||||
|             return json::makeWaypoint( | ||||
|                 phantom.location, | ||||
|                 util::coordinate_calculation::fccApproximateDistance(phantom.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,7 +66,7 @@ class BaseAPI | ||||
|             // TODO: check forward/reverse
 | ||||
|             return json::makeWaypoint( | ||||
|                 phantom.location, | ||||
|                 util::coordinate_calculation::fccApproximateDistance(phantom.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<fbresult::WaypointBuilder>(*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) | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -484,7 +484,7 @@ template <typename RTreeT, typename DataFacadeT> 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 <typename RTreeT, typename DataFacadeT> 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 <typename RTreeT, typename DataFacadeT> 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 <typename RTreeT, typename DataFacadeT> 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 <typename RTreeT, typename DataFacadeT> 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<bool, bool> CheckSegmentExclude(const CandidateSegment &segment) const | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -428,7 +428,7 @@ template <typename FacadeT> 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))); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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
 | ||||
|  | ||||
							
								
								
									
										26
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -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", | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
| @ -25,7 +25,8 @@ std::pair<short, short> 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<short, short>(0, source_node.GetBearing(traversed_in_reverse)); | ||||
|     } | ||||
| @ -41,7 +42,8 @@ std::pair<short, short> 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<short, short>(target_node.GetBearing(traversed_in_reverse), 0); | ||||
|     } | ||||
|  | ||||
| @ -263,7 +263,7 @@ void trimShortSegments(std::vector<RouteStep> &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<RouteStep> &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<RouteStep> assignRelativeLocations(std::vector<RouteStep> 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<RouteStep> assignRelativeLocations(std::vector<RouteStep> 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 && | ||||
|  | ||||
| @ -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] = | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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
 | ||||
|  | ||||
| @ -214,7 +214,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &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<Algorithm> &engine_working_data, | ||||
|             reconstructed_indices, | ||||
|             [&trace_distance, &trace_coordinates](const std::pair<std::size_t, std::size_t> &prev, | ||||
|                                                   const std::pair<std::size_t, std::size_t> &curr) { | ||||
|                 trace_distance += util::coordinate_calculation::haversineDistance( | ||||
|                 trace_distance += util::coordinate_calculation::greatCircleDistance( | ||||
|                     trace_coordinates[prev.first], trace_coordinates[curr.first]); | ||||
|             }); | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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<util::Coordinate>::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<util::Coordinate> &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<util::Coordinate> &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,7 +924,7 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector<util::Coordinate> coord | ||||
|         [&coordinate_index, &distance_to_current_coordinate, &coordinates]() { | ||||
|             const auto new_distance = | ||||
|                 distance_to_current_coordinate + | ||||
|                 util::coordinate_calculation::haversineDistance(coordinates[coordinate_index - 1], | ||||
|                 util::coordinate_calculation::greatCircleDistance(coordinates[coordinate_index - 1], | ||||
|                                                                   coordinates[coordinate_index]); | ||||
|             return new_distance; | ||||
|         }; | ||||
| @ -941,7 +941,7 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector<util::Coordinate> coord | ||||
|             coordinates.erase(coordinates.begin() + length_cache.size(), coordinates.end()); | ||||
| 
 | ||||
|         const auto distance_between_last_coordinates = | ||||
|             util::coordinate_calculation::haversineDistance(*(coordinates.end() - 2), | ||||
|             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<util::Coordinate> &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<util::Coordinate> | ||||
|     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) | ||||
|         { | ||||
|  | ||||
| @ -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}); | ||||
|     } | ||||
|  | ||||
| @ -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,7 +274,8 @@ 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( | ||||
|     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 > | ||||
| @ -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; | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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)]); | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -56,7 +56,7 @@ std::unordered_set<EdgeID> 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; | ||||
|     }; | ||||
|  | ||||
| @ -452,7 +452,7 @@ 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], | ||||
|             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.; | ||||
| 
 | ||||
|  | ||||
| @ -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
 | ||||
|  | ||||
| @ -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<double>(util::toFloating(coordinate_1.lon)); | ||||
|     const auto lat1 = static_cast<double>(util::toFloating(coordinate_1.lat)); | ||||
|     const auto lon2 = static_cast<double>(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<int>(coordinate_1.lon); | ||||
|     auto lat1 = static_cast<int>(coordinate_1.lat); | ||||
|     auto lon2 = static_cast<int>(coordinate_2.lon); | ||||
|     auto lat2 = static_cast<int>(coordinate_2.lat); | ||||
|     BOOST_ASSERT(lon1 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lat1 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lon2 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lat2 != std::numeric_limits<int>::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<int>(coordinate_1.lon); | ||||
|     auto lat1 = static_cast<int>(coordinate_1.lat); | ||||
|     auto lon2 = static_cast<int>(coordinate_2.lon); | ||||
|     auto lat2 = static_cast<int>(coordinate_2.lat); | ||||
|     BOOST_ASSERT(lat1 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lon1 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lat2 != std::numeric_limits<int>::min()); | ||||
|     BOOST_ASSERT(lon2 != std::numeric_limits<int>::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<double>(toFloating(second_coordinate.lon - first_coordinate.lon)); | ||||
|     const double lon_delta = detail::degToRad(lon_diff); | ||||
|     const double lat1 = detail::degToRad(static_cast<double>(toFloating(first_coordinate.lat))); | ||||
|     const double lat2 = detail::degToRad(static_cast<double>(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<double>(util::toFloating(coordinate_1.lon)); | ||||
|     const auto lat1 = static_cast<double>(util::toFloating(coordinate_1.lat)); | ||||
|     const auto lon2 = static_cast<double>(util::toFloating(coordinate_2.lon)); | ||||
|     const auto lat2 = static_cast<double>(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<double>::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<Coordinate> &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<Coordinate> &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; | ||||
| 
 | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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
 | ||||
|     }); | ||||
| }); | ||||
| @ -1,7 +1,10 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <mapbox/geometry.hpp> | ||||
| #include <mapbox/geometry/box.hpp> | ||||
| #include <mapbox/geometry/multi_line_string.hpp> | ||||
| #include <mapbox/geometry/polygon.hpp> | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <cmath> | ||||
| #include <cstdint> | ||||
| #include <limits> | ||||
| @ -19,6 +22,14 @@ using point             = geometry::point<double>; | ||||
| using polygon           = geometry::polygon<double>; | ||||
| 
 | ||||
| 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 <point, index, t> 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<point, unsigned, double> pointOnLine(const line_string& line, point p) { | ||||
|     std::tuple<point, unsigned, double> pointOnLine(const line_string& line, point p) const { | ||||
|         double minDist = std::numeric_limits<double>::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
 | ||||
| @ -1,5 +1,6 @@ | ||||
| #include <mapbox/cheap_ruler.hpp> | ||||
| #include <gtest/gtest.h> | ||||
| #include <random> | ||||
| 
 | ||||
| #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); | ||||
| 
 | ||||
| @ -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<std::int64_t> 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<std::int64_t> 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); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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<Coordinate>{{FloatLongitude{.00}, FloatLatitude{.00}}, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user