Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1e76d04d1 | |||
| 451bbe3021 | |||
| 88a76aaecf | |||
| 87428f8fc9 | |||
| 6c9ddde682 | |||
| b4b148e3dc | |||
| 4a84ca3197 | |||
| df182ebc38 | |||
| c86864976c | |||
| c3dd77d32b | |||
| 2357d1c095 | |||
| 7cd70679f1 | |||
| 08c1ac0daf | |||
| 48237b30ea | |||
| cac1298864 | |||
| 83e6679d61 | |||
| f3ea86b611 | |||
| f3de53c363 | |||
| 19434d42b4 | |||
| ea24ea64f2 | |||
| 39f5cf1c22 | |||
| 91384ecd8c | |||
| 5c28eabbe0 | |||
| 42dd45b29b | |||
| 6f4095f23f | |||
| 9c6c02d85b | |||
| 47afe60e5f | |||
| 0471ace55d | |||
| 49e2a4ec07 | |||
| 991c5f5d5d | |||
| 87c77e7d77 | |||
| 2cf120fc49 | |||
| d4eaea1e7d | |||
| 51a13675d4 | |||
| af4cb96aa5 | |||
| 439a7ba661 | |||
| a0ff0b1258 | |||
| 1cc9a2f4a1 | |||
| a3cf7f09e8 | |||
| 831a536224 | |||
| 7df00683e1 | |||
| 0c0803c77b | |||
| 7c5d56afcb | |||
| 892b9dff4a | |||
| 04a8c1833c | |||
| c217ff815c | |||
| 893c9f7326 | |||
| 84fa7ae353 | |||
| bb3256573b | |||
| 96d9ef3951 | |||
| 11572702e9 | |||
| 6d16bb5b25 | |||
| 89eb2a3778 | |||
| 87408cfd73 | |||
| dd4066c46e | |||
| 3f559211a4 | |||
| 5892c6ea09 | |||
| dea0063a56 | |||
| eec270968e | |||
| 056a7422e0 | |||
| 3d3fea768c | |||
| 1a6c16fea1 | |||
| 3c56385ba8 | |||
| 1947671ae3 | |||
| 3189f24a17 | |||
| dd5c730a01 | |||
| da1dbcfb34 | |||
| 8f5091f711 | |||
| 0da7302d62 | |||
| f0b40c1948 | |||
| ecefb4a20e | |||
| 9b1861e017 | |||
| 4fb041391f | |||
| 64cc7d8aac | |||
| 556223d43b | |||
| 0b1e82105e | |||
| c9ad8736b0 | |||
| cded2501a5 | |||
| 4d94ec2792 | |||
| 7970bc4ad6 | |||
| f84ce976ea | |||
| ce9a4666f3 | |||
| ff55b4e001 | |||
| 8040af329b | |||
| b8c059b5c2 | |||
| 4e2e2059b1 | |||
| 922599a8ca | |||
| 5bc0595591 | |||
| 0f600c9262 | |||
| 9338d418c8 | |||
| 4d56b8ff0d | |||
| 92b4f14db6 | |||
| a1f1da4c16 | |||
| c337d55d45 | |||
| be5f231641 | |||
| c19fae4a43 | |||
| 0831e71438 | |||
| c44a370dd3 | |||
| 9f5e79501e | |||
| cf5e722578 | |||
| f12bb2fa2f | |||
| 28d878ed23 | |||
| 6db16e950a | |||
| 862f8d6ff3 | |||
| 8c67dd4504 | |||
| 23d79bde54 | |||
| 410d561b4c | |||
| 8ab38b126c | |||
| c13f1aa89d | |||
| b4bf0ec5fe | |||
| f7b7dbf51a | |||
| 41c9f94e5f | |||
| 77adbca138 | |||
| f3e06b41dd | |||
| ee4b8618f8 | |||
| 58973a4fd1 | |||
| 4b8017d412 | |||
| 64d4d58a0d | |||
| 5d83fa1e4c | |||
| 7a6aa6f1a7 | |||
| e5d964492a | |||
| bb2baa82aa | |||
| 0b5875a412 | |||
| 9a2b8cb16d | |||
| 5fb6db7a9a | |||
| c1647c99c8 | |||
| 39d6c33b32 | |||
| 9b75f618e8 | |||
| 225049ffa7 | |||
| 2df832a95e | |||
| 75912b3662 | |||
| c9a19c954e | |||
| 9a19086926 | |||
| 90e8a3e1dc | |||
| 0270ee59b4 | |||
| 5728af4a2a | |||
| 6cf19ac4cf | |||
| 3f81f6b441 | |||
| 669aa9e672 | |||
| 1d3afd5c38 | |||
| c53a448589 | |||
| cb82376083 | |||
| 9d10490613 | |||
| 1cc7d3ddfb | |||
| aad3d8aa1e | |||
| 9258791811 | |||
| 19d5912a93 | |||
| a4770feac4 | |||
| c8c6f8c2e7 | |||
| d7f9c31d0b | |||
| 44b802c053 | |||
| 99f18051f6 | |||
| 99f94969aa | |||
| bc6d5bbde2 | |||
| 6aa5ab5904 | |||
| 0c64503218 | |||
| e15ba88c0b | |||
| 2f9d1d3db2 | |||
| 42e6e974ac | |||
| 5a97e7a7ce | |||
| 8c54794d5a | |||
| e377a19c10 | |||
| 0fb6e9bf3f | |||
| d6a8690425 | |||
| cc65446785 | |||
| 487df70eb3 | |||
| aa79c41804 | |||
| 7faadb1233 | |||
| 5c8a895471 | |||
| e932a8253a | |||
| 84097964b7 | |||
| c2a35b35ad | |||
| f6612e2afa | |||
| 09378f28fd | |||
| 01ddfbcba3 | |||
| 0468d7a7c5 | |||
| 39bc0fd330 | |||
| 53dbb1eac2 | |||
| f5bc843fe6 | |||
| c78dff9a15 | |||
| 25fea558ba | |||
| b1c84b598f |
+4
-2
@@ -80,7 +80,7 @@ add_executable(osrm-extract src/tools/extract.cpp)
|
|||||||
add_executable(osrm-contract src/tools/contract.cpp)
|
add_executable(osrm-contract src/tools/contract.cpp)
|
||||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
|
||||||
add_library(osrm_extract $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_extract $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_contract $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_contract $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
|
||||||
@@ -94,6 +94,7 @@ add_executable(server-tests EXCLUDE_FROM_ALL unit_tests/server_tests.cpp ${Serve
|
|||||||
# Benchmarks
|
# Benchmarks
|
||||||
add_executable(rtree-bench EXCLUDE_FROM_ALL src/benchmarks/static_rtree.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(rtree-bench EXCLUDE_FROM_ALL src/benchmarks/static_rtree.cpp $<TARGET_OBJECTS:UTIL>)
|
||||||
|
|
||||||
|
target_include_directories(engine-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
||||||
target_include_directories(util-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
target_include_directories(util-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
||||||
target_include_directories(rtree-bench PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
target_include_directories(rtree-bench PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
||||||
|
|
||||||
@@ -381,9 +382,10 @@ set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp incl
|
|||||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp)
|
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp)
|
||||||
set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
||||||
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
||||||
#set(StorageHeader include/storage/storage.hpp include/storage/storage_config.hpp)
|
set(StorageHeader include/storage/storage.hpp include/storage/storage_config.hpp)
|
||||||
install(FILES ${EngineHeader} DESTINATION include/osrm/engine)
|
install(FILES ${EngineHeader} DESTINATION include/osrm/engine)
|
||||||
install(FILES ${UtilHeader} DESTINATION include/osrm/util)
|
install(FILES ${UtilHeader} DESTINATION include/osrm/util)
|
||||||
|
install(FILES ${StorageHeader} DESTINATION include/osrm/storage)
|
||||||
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
|
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
|
||||||
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
|
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
|
||||||
install(FILES ${LibraryGlob} DESTINATION include/osrm)
|
install(FILES ${LibraryGlob} DESTINATION include/osrm)
|
||||||
|
|||||||
+2
-1
@@ -29,7 +29,8 @@ int main(int argc, const char *argv[]) try
|
|||||||
using namespace osrm;
|
using namespace osrm;
|
||||||
|
|
||||||
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
||||||
EngineConfig config{argv[1]};
|
EngineConfig config;
|
||||||
|
config.storage_config = {argv[1]};
|
||||||
config.use_shared_memory = false;
|
config.use_shared_memory = false;
|
||||||
|
|
||||||
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
@routing @guidance
|
||||||
|
Feature: Basic Roundabout
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Right
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | d | e |
|
||||||
|
| | | | f | g |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| bfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive |
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Right Curved Right
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | | |
|
||||||
|
| | | f | d | |
|
||||||
|
| | | | g | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| bfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive |
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Right Curved Left
|
||||||
|
Given the node map
|
||||||
|
| | | | | e |
|
||||||
|
| | | | d | g |
|
||||||
|
| a | b | c | f | |
|
||||||
|
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| cfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, cfg, cfg | depart, ramp-slight-right, arrive |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Left
|
||||||
|
Given the node map
|
||||||
|
| | | | f | g |
|
||||||
|
| a | b | c | d | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| bfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive |
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Left Curved Left
|
||||||
|
Given the node map
|
||||||
|
| | | | g | e |
|
||||||
|
| | | f | d | |
|
||||||
|
| a | b | c | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| bfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive |
|
||||||
|
|
||||||
|
Scenario: Ramp Exit Left Curved Right
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | f | |
|
||||||
|
| | | | d | g |
|
||||||
|
| | | | | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| cfg | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| a,g | abcde, cfg, cfg | depart, ramp-slight-left, arrive |
|
||||||
|
|
||||||
|
Scenario: On Ramp Right
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | d | e |
|
||||||
|
| f | g | | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| fgd | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| f,e | abcde, fgd, fgd | depart, merge-slight-left, arrive |
|
||||||
|
|
||||||
|
Scenario: On Ramp Left
|
||||||
|
Given the node map
|
||||||
|
| f | g | | | |
|
||||||
|
| a | b | c | d | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| fgd | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| f,e | abcde, fgd, fgd | depart, merge-slight-right, arrive |
|
||||||
|
|
||||||
|
Scenario: Highway Fork
|
||||||
|
Given the node map
|
||||||
|
| | | | | d | e |
|
||||||
|
| a | b | c | | | |
|
||||||
|
| | | | | f | g |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| cfg | motorway |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde, abcde | depart, fork-left, arrive |
|
||||||
|
| a,g | abcde, cfg, cfg | depart, fork-right, arrive |
|
||||||
|
|
||||||
|
Scenario: Fork After Ramp
|
||||||
|
Given the node map
|
||||||
|
| | | | | d | e |
|
||||||
|
| a | b | c | | | |
|
||||||
|
| | | | | f | g |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | motorway_link |
|
||||||
|
| cde | motorway |
|
||||||
|
| cfg | motorway |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abc, cde, cde | depart, fork-left, arrive |
|
||||||
|
| a,g | abc, cfg, cfg | depart, fork-right, arrive |
|
||||||
|
|
||||||
|
Scenario: On And Off Ramp Right
|
||||||
|
Given the node map
|
||||||
|
| a | b | | c | | d | e |
|
||||||
|
| f | g | | | | h | i |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| fgc | motorway_link |
|
||||||
|
| chi | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| f,e | fgc, abcde, abcde | depart, merge-slight-left, arrive |
|
||||||
|
| a,i | abcde, chi, chi | depart, ramp-slight-right, arrive |
|
||||||
|
| f,i | fgc, chi, chi | depart, turn-slight-right, arrive |
|
||||||
|
|
||||||
|
Scenario: On And Off Ramp Left
|
||||||
|
Given the node map
|
||||||
|
| f | g | | | | h | i |
|
||||||
|
| a | b | | c | | d | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abcde | motorway |
|
||||||
|
| fgc | motorway_link |
|
||||||
|
| chi | motorway_link |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | abcde, abcde | depart, arrive |
|
||||||
|
| f,e | fgc, abcde, abcde | depart, merge-slight-right, arrive |
|
||||||
|
| a,i | abcde, chi, chi | depart, ramp-slight-left, arrive |
|
||||||
|
| f,i | fgc, chi, chi | depart, turn-slight-left, arrive |
|
||||||
|
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
@routing @guidance
|
||||||
|
Feature: Basic Roundabout
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Enter and Exit
|
||||||
|
Given the node map
|
||||||
|
| | | a | | |
|
||||||
|
| | | b | | |
|
||||||
|
| h | g | | c | d |
|
||||||
|
| | | e | | |
|
||||||
|
| | | f | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | roundabout |
|
||||||
|
| ab | no |
|
||||||
|
| cd | no |
|
||||||
|
| ef | no |
|
||||||
|
| gh | no |
|
||||||
|
| bcegb | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | ab,cd,cd | depart, roundabout-exit-1, arrive |
|
||||||
|
| a,f | ab,ef,ef | depart, roundabout-exit-2, arrive |
|
||||||
|
| a,h | ab,gh,gh | depart, roundabout-exit-3, arrive |
|
||||||
|
| d,f | cd,ef,ef | depart, roundabout-exit-1, arrive |
|
||||||
|
| d,h | cd,gh,gh | depart, roundabout-exit-2, arrive |
|
||||||
|
| d,a | cd,ab,ab | depart, roundabout-exit-3, arrive |
|
||||||
|
| f,h | ef,gh,gh | depart, roundabout-exit-1, arrive |
|
||||||
|
| f,a | ef,ab,ab | depart, roundabout-exit-2, arrive |
|
||||||
|
| f,d | ef,cd,cd | depart, roundabout-exit-3, arrive |
|
||||||
|
| h,a | gh,ab,ab | depart, roundabout-exit-1, arrive |
|
||||||
|
| h,d | gh,cd,cd | depart, roundabout-exit-2, arrive |
|
||||||
|
| h,f | gh,ef,ef | depart, roundabout-exit-3, arrive |
|
||||||
|
|
||||||
|
Scenario: Only Enter
|
||||||
|
Given the node map
|
||||||
|
| | | a | | |
|
||||||
|
| | | b | | |
|
||||||
|
| h | g | | c | d |
|
||||||
|
| | | e | | |
|
||||||
|
| | | f | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | roundabout |
|
||||||
|
| ab | no |
|
||||||
|
| cd | no |
|
||||||
|
| ef | no |
|
||||||
|
| gh | no |
|
||||||
|
| bcegb | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,b | ab,ab | depart, arrive |
|
||||||
|
| a,c | ab,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| a,e | ab,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| a,g | ab,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| d,c | cd,cd | depart, arrive |
|
||||||
|
| d,e | cd,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| d,g | cd,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| d,b | cd,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| f,e | ef,ef | depart, arrive |
|
||||||
|
| f,g | ef,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| f,b | ef,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| f,c | ef,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| h,g | gh,gh | depart, arrive |
|
||||||
|
| h,b | gh,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| h,c | gh,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
| h,e | gh,bcegb | depart, roundabout-enter, arrive |
|
||||||
|
|
||||||
|
Scenario: Only Exit
|
||||||
|
Given the node map
|
||||||
|
| | | a | | |
|
||||||
|
| | | b | | |
|
||||||
|
| h | g | | c | d |
|
||||||
|
| | | e | | |
|
||||||
|
| | | f | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | roundabout |
|
||||||
|
| ab | no |
|
||||||
|
| cd | no |
|
||||||
|
| ef | no |
|
||||||
|
| gh | no |
|
||||||
|
| bcegb | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| b,a | ab,ab | depart, arrive |
|
||||||
|
| b,d | bcegb,cd,cd | depart, roundabout-exit-1, arrive |
|
||||||
|
| b,f | bcegb,ef,ef | depart, roundabout-exit-2, arrive |
|
||||||
|
| b,h | bcegb,gh,gh | depart, roundabout-exit-3, arrive |
|
||||||
|
| c,d | cd,cd | depart, arrive |
|
||||||
|
| c,f | bcegb,ef,ef | depart, roundabout-exit-1, arrive |
|
||||||
|
| c,h | bcegb,gh,gh | depart, roundabout-exit-2, arrive |
|
||||||
|
| c,a | bcegb,ab,ab | depart, roundabout-exit-3, arrive |
|
||||||
|
| e,f | ef,ef | depart, arrive |
|
||||||
|
| e,h | bcegb,gh,gh | depart, roundabout-exit-1, arrive |
|
||||||
|
| e,a | bcegb,ab,ab | depart, roundabout-exit-2, arrive |
|
||||||
|
| e,d | bcegb,cd,cd | depart, roundabout-exit-3, arrive |
|
||||||
|
| g,h | gh,gh | depart, arrive |
|
||||||
|
| g,a | bcegb,ab,ab | depart, roundabout-exit-1, arrive |
|
||||||
|
| g,d | bcegb,cd,cd | depart, roundabout-exit-2, arrive |
|
||||||
|
| g,f | bcegb,ef,ef | depart, roundabout-exit-3, arrive |
|
||||||
|
|
||||||
|
Scenario: Drive Around
|
||||||
|
Given the node map
|
||||||
|
| | | a | | |
|
||||||
|
| | | b | | |
|
||||||
|
| h | g | | c | d |
|
||||||
|
| | | e | | |
|
||||||
|
| | | f | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | roundabout |
|
||||||
|
| ab | no |
|
||||||
|
| cd | no |
|
||||||
|
| ef | no |
|
||||||
|
| gh | no |
|
||||||
|
| bcegb | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| b,c | bcegb,bcegb | depart, arrive |
|
||||||
|
| b,e | bcegb,bcegb | depart, arrive |
|
||||||
|
| b,g | bcegb,bcegb | depart, arrive |
|
||||||
|
| c,e | bcegb,bcegb | depart, arrive |
|
||||||
|
| c,g | bcegb,bcegb | depart, arrive |
|
||||||
|
| c,b | bcegb,bcegb | depart, arrive |
|
||||||
|
| e,g | bcegb,bcegb | depart, arrive |
|
||||||
|
| e,b | bcegb,bcegb | depart, arrive |
|
||||||
|
| e,c | bcegb,bcegb | depart, arrive |
|
||||||
|
| g,b | bcegb,bcegb | depart, arrive |
|
||||||
|
| g,c | bcegb,bcegb | depart, arrive |
|
||||||
|
| g,e | bcegb,bcegb | depart, arrive |
|
||||||
|
|
||||||
|
Scenario: Mixed Entry and Exit
|
||||||
|
Given the node map
|
||||||
|
| | a | | c | |
|
||||||
|
| l | | b | | d |
|
||||||
|
| | k | | e | |
|
||||||
|
| j | | h | | f |
|
||||||
|
| | i | | g | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | roundabout | oneway |
|
||||||
|
| abc | no | yes |
|
||||||
|
| def | no | yes |
|
||||||
|
| ghi | no | yes |
|
||||||
|
| jkl | no | yes |
|
||||||
|
| behkb | yes | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | abc,abc,abc | depart, roundabout-exit-1, arrive |
|
||||||
|
| a,f | abc,def,def | depart, roundabout-exit-2, arrive |
|
||||||
|
| a,i | abc,ghi,ghi | depart, roundabout-exit-3, arrive |
|
||||||
|
| a,l | abc,jkl,jkl | depart, roundabout-exit-4, arrive |
|
||||||
|
| d,f | def,def,def | depart, roundabout-exit-1, arrive |
|
||||||
|
| d,i | def,ghi,ghi | depart, roundabout-exit-2, arrive |
|
||||||
|
| d,l | def,jkl,jkl | depart, roundabout-exit-3, arrive |
|
||||||
|
| d,c | def,abc,abc | depart, roundabout-exit-4, arrive |
|
||||||
|
| g,i | ghi,ghi,ghi | depart, roundabout-exit-1, arrive |
|
||||||
|
| g,l | ghi,jkl,jkl | depart, roundabout-exit-2, arrive |
|
||||||
|
| g,c | ghi,abc,abc | depart, roundabout-exit-3, arrive |
|
||||||
|
| g,f | ghi,edf,edf | depart, roundabout-exit-4, arrive |
|
||||||
|
| j,l | jkl,jkl,jkl | depart, roundabout-exit-1, arrive |
|
||||||
|
| j,c | jkl,abc,abc | depart, roundabout-exit-2, arrive |
|
||||||
|
| j,f | jkl,def,def | depart, roundabout-exit-3, arrive |
|
||||||
|
| j,i | jkl,ghi,ghi | depart, roundabout-exit-4, arrive |
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "engine/hint.hpp"
|
#include "engine/hint.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/range/algorithm/transform.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -33,24 +34,23 @@ class BaseAPI
|
|||||||
|
|
||||||
util::json::Array waypoints;
|
util::json::Array waypoints;
|
||||||
waypoints.values.resize(parameters.coordinates.size());
|
waypoints.values.resize(parameters.coordinates.size());
|
||||||
waypoints.values[0] = MakeWaypoint(parameters.coordinates.front(),
|
waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
|
||||||
segment_end_coordinates.front().source_phantom);
|
|
||||||
|
|
||||||
auto coord_iter = std::next(parameters.coordinates.begin());
|
|
||||||
auto out_iter = std::next(waypoints.values.begin());
|
auto out_iter = std::next(waypoints.values.begin());
|
||||||
for (const auto &phantoms : segment_end_coordinates)
|
boost::range::transform(segment_end_coordinates, out_iter,
|
||||||
{
|
[this](const PhantomNodes &phantom_pair)
|
||||||
*out_iter++ = MakeWaypoint(*coord_iter++, phantoms.target_phantom);
|
{
|
||||||
}
|
return MakeWaypoint(phantom_pair.target_phantom);
|
||||||
|
});
|
||||||
return waypoints;
|
return waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
|
||||||
util::json::Object MakeWaypoint(const util::Coordinate input_coordinate,
|
// protected:
|
||||||
const PhantomNode &phantom) const
|
util::json::Object MakeWaypoint(const PhantomNode &phantom) const
|
||||||
{
|
{
|
||||||
return json::makeWaypoint(phantom.location, facade.get_name_for_id(phantom.name_id),
|
return json::makeWaypoint(phantom.location, facade.GetNameForID(phantom.name_id),
|
||||||
Hint{input_coordinate, phantom, facade.GetCheckSum()});
|
Hint{phantom, facade.GetCheckSum()});
|
||||||
}
|
}
|
||||||
|
|
||||||
const datafacade::BaseDataFacade &facade;
|
const datafacade::BaseDataFacade &facade;
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ class MatchAPI final : public RouteAPI
|
|||||||
response.values["code"] = "ok";
|
response.values["code"] = "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
|
||||||
|
// protected:
|
||||||
|
|
||||||
// FIXME this logic is a little backwards. We should change the output format of the
|
// FIXME this logic is a little backwards. We should change the output format of the
|
||||||
// map_matching
|
// map_matching
|
||||||
// routing algorithm to be easier to consume here.
|
// routing algorithm to be easier to consume here.
|
||||||
@@ -98,7 +100,7 @@ class MatchAPI final : public RouteAPI
|
|||||||
}
|
}
|
||||||
const auto &phantom =
|
const auto &phantom =
|
||||||
sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index];
|
sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index];
|
||||||
auto waypoint = BaseAPI::MakeWaypoint(parameters.coordinates[trace_index], phantom);
|
auto waypoint = BaseAPI::MakeWaypoint(phantom);
|
||||||
waypoint.values["matchings_index"] = matching_index.sub_matching_index;
|
waypoint.values["matchings_index"] = matching_index.sub_matching_index;
|
||||||
waypoint.values["waypoint_index"] = matching_index.point_index;
|
waypoint.values["waypoint_index"] = matching_index.point_index;
|
||||||
waypoints.values.push_back(std::move(waypoint));
|
waypoints.values.push_back(std::move(waypoint));
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ class NearestAPI final : public BaseAPI
|
|||||||
waypoints.values.begin(),
|
waypoints.values.begin(),
|
||||||
[this](const PhantomNodeWithDistance &phantom_with_distance)
|
[this](const PhantomNodeWithDistance &phantom_with_distance)
|
||||||
{
|
{
|
||||||
auto waypoint = MakeWaypoint(parameters.coordinates.front(),
|
auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
|
||||||
phantom_with_distance.phantom_node);
|
|
||||||
waypoint.values["distance"] = phantom_with_distance.distance;
|
waypoint.values["distance"] = phantom_with_distance.distance;
|
||||||
return waypoint;
|
return waypoint;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class RouteAPI : public BaseAPI
|
|||||||
response.values["code"] = "ok";
|
response.values["code"] = "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
|
||||||
|
// protected:
|
||||||
template <typename ForwardIter>
|
template <typename ForwardIter>
|
||||||
util::json::Value MakeGeometry(ForwardIter begin, ForwardIter end) const
|
util::json::Value MakeGeometry(ForwardIter begin, ForwardIter end) const
|
||||||
{
|
{
|
||||||
@@ -71,7 +72,7 @@ class RouteAPI : public BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
|
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
|
||||||
std::vector<std::vector<PathData>> unpacked_path_segments,
|
const std::vector<std::vector<PathData>> &unpacked_path_segments,
|
||||||
const std::vector<bool> &source_traversed_in_reverse,
|
const std::vector<bool> &source_traversed_in_reverse,
|
||||||
const std::vector<bool> &target_traversed_in_reverse) const
|
const std::vector<bool> &target_traversed_in_reverse) const
|
||||||
{
|
{
|
||||||
@@ -81,7 +82,6 @@ class RouteAPI : public BaseAPI
|
|||||||
legs.reserve(number_of_legs);
|
legs.reserve(number_of_legs);
|
||||||
leg_geometries.reserve(number_of_legs);
|
leg_geometries.reserve(number_of_legs);
|
||||||
|
|
||||||
unpacked_path_segments = guidance::postProcess(std::move(unpacked_path_segments));
|
|
||||||
for (auto idx : util::irange(0UL, number_of_legs))
|
for (auto idx : util::irange(0UL, number_of_legs))
|
||||||
{
|
{
|
||||||
const auto &phantoms = segment_end_coordinates[idx];
|
const auto &phantoms = segment_end_coordinates[idx];
|
||||||
@@ -93,19 +93,47 @@ class RouteAPI : public BaseAPI
|
|||||||
auto leg_geometry = guidance::assembleGeometry(
|
auto leg_geometry = guidance::assembleGeometry(
|
||||||
BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
|
BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
|
||||||
auto leg = guidance::assembleLeg(BaseAPI::facade, path_data, leg_geometry,
|
auto leg = guidance::assembleLeg(BaseAPI::facade, path_data, leg_geometry,
|
||||||
phantoms.source_phantom, phantoms.target_phantom,
|
phantoms.target_phantom, reversed_target);
|
||||||
reversed_source, reversed_target);
|
|
||||||
|
|
||||||
if (parameters.steps)
|
if (parameters.steps)
|
||||||
{
|
{
|
||||||
leg.steps = guidance::assembleSteps(
|
auto steps = guidance::assembleSteps(
|
||||||
BaseAPI::facade, path_data, leg_geometry, phantoms.source_phantom,
|
BaseAPI::facade, path_data, leg_geometry, phantoms.source_phantom,
|
||||||
phantoms.target_phantom, reversed_source, reversed_target);
|
phantoms.target_phantom, reversed_source, reversed_target);
|
||||||
|
|
||||||
|
/* Perform step-based post-processing.
|
||||||
|
*
|
||||||
|
* Using post-processing on basis of route-steps for a single leg at a time
|
||||||
|
* comes at the cost that we cannot count the correct exit for roundabouts.
|
||||||
|
* We can only emit the exit nr/intersections up to/starting at a part of the leg.
|
||||||
|
* If a roundabout is not terminated in a leg, we will end up with a enter-roundabout
|
||||||
|
* and exit-roundabout-nr where the exit nr is out of sync with the previous enter.
|
||||||
|
*
|
||||||
|
* | S |
|
||||||
|
* * *
|
||||||
|
* ----* * ----
|
||||||
|
* T
|
||||||
|
* ----* * ----
|
||||||
|
* V * *
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
*
|
||||||
|
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to take
|
||||||
|
* the second exit, even though counting from S it would be the third.
|
||||||
|
* For S, we only emit `roundabout` without an exit number, showing that we enter a roundabout
|
||||||
|
* to find a via point.
|
||||||
|
* The same exit will be emitted, though, if we should start routing at S, making
|
||||||
|
* the overall response consistent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
leg.steps = guidance::postProcess(std::move(steps));
|
||||||
|
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry),leg.steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
leg_geometries.push_back(std::move(leg_geometry));
|
leg_geometries.push_back(std::move(leg_geometry));
|
||||||
legs.push_back(std::move(leg));
|
legs.push_back(std::move(leg));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto route = guidance::assembleRoute(legs);
|
auto route = guidance::assembleRoute(legs);
|
||||||
boost::optional<util::json::Value> json_overview;
|
boost::optional<util::json::Value> json_overview;
|
||||||
if (parameters.overview != RouteParameters::OverviewType::False)
|
if (parameters.overview != RouteParameters::OverviewType::False)
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ struct RouteParameters : public BaseParameters
|
|||||||
const bool alternatives_,
|
const bool alternatives_,
|
||||||
const GeometriesType geometries_,
|
const GeometriesType geometries_,
|
||||||
const OverviewType overview_,
|
const OverviewType overview_,
|
||||||
std::vector<boost::optional<bool>> uturns_,
|
const boost::optional<bool> uturns_,
|
||||||
Args... args_)
|
Args... args_)
|
||||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||||
geometries{geometries_}, overview{overview_}, uturns{std::move(uturns_)}
|
geometries{geometries_}, overview{overview_}, uturns{uturns_}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,12 +71,11 @@ struct RouteParameters : public BaseParameters
|
|||||||
bool alternatives = true;
|
bool alternatives = true;
|
||||||
GeometriesType geometries = GeometriesType::Polyline;
|
GeometriesType geometries = GeometriesType::Polyline;
|
||||||
OverviewType overview = OverviewType::Simplified;
|
OverviewType overview = OverviewType::Simplified;
|
||||||
std::vector<boost::optional<bool>> uturns;
|
boost::optional<bool> uturns;
|
||||||
|
|
||||||
bool IsValid() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
return coordinates.size() >= 2 && BaseParameters::IsValid() &&
|
return coordinates.size() >= 2 && BaseParameters::IsValid();
|
||||||
(uturns.empty() || uturns.size() == coordinates.size());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
|
#include <boost/range/algorithm/transform.hpp>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
@@ -66,19 +68,19 @@ class TableAPI final : public BaseAPI
|
|||||||
response.values["code"] = "ok";
|
response.values["code"] = "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
|
||||||
|
// protected:
|
||||||
virtual util::json::Array MakeWaypoints(const std::vector<PhantomNode> &phantoms) const
|
virtual util::json::Array MakeWaypoints(const std::vector<PhantomNode> &phantoms) const
|
||||||
{
|
{
|
||||||
util::json::Array json_waypoints;
|
util::json::Array json_waypoints;
|
||||||
json_waypoints.values.reserve(phantoms.size());
|
json_waypoints.values.reserve(phantoms.size());
|
||||||
BOOST_ASSERT(phantoms.size() == parameters.coordinates.size());
|
BOOST_ASSERT(phantoms.size() == parameters.coordinates.size());
|
||||||
auto phantom_iter = phantoms.begin();
|
|
||||||
auto coordinate_iter = parameters.coordinates.begin();
|
boost::range::transform(phantoms, std::back_inserter(json_waypoints.values),
|
||||||
for (; phantom_iter != phantoms.end() && coordinate_iter != parameters.coordinates.end();
|
[this](const PhantomNode &phantom)
|
||||||
++phantom_iter, ++coordinate_iter)
|
{
|
||||||
{
|
return BaseAPI::MakeWaypoint(phantom);
|
||||||
json_waypoints.values.push_back(BaseAPI::MakeWaypoint(*coordinate_iter, *phantom_iter));
|
});
|
||||||
}
|
|
||||||
return json_waypoints;
|
return json_waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,12 +89,12 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
util::json::Array json_waypoints;
|
util::json::Array json_waypoints;
|
||||||
json_waypoints.values.reserve(indices.size());
|
json_waypoints.values.reserve(indices.size());
|
||||||
for (auto idx : indices)
|
boost::range::transform(indices, std::back_inserter(json_waypoints.values),
|
||||||
{
|
[this, phantoms](const std::size_t idx)
|
||||||
BOOST_ASSERT(idx < phantoms.size() && idx < parameters.coordinates.size());
|
{
|
||||||
json_waypoints.values.push_back(
|
BOOST_ASSERT(idx < phantoms.size());
|
||||||
BaseAPI::MakeWaypoint(parameters.coordinates[idx], phantoms[idx]));
|
return BaseAPI::MakeWaypoint(phantoms[idx]);
|
||||||
}
|
});
|
||||||
return json_waypoints;
|
return json_waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ class TripAPI final : public RouteAPI
|
|||||||
BOOST_ASSERT(sub_trips.size() == sub_routes.size());
|
BOOST_ASSERT(sub_trips.size() == sub_routes.size());
|
||||||
for (auto index : util::irange<std::size_t>(0UL, sub_trips.size()))
|
for (auto index : util::irange<std::size_t>(0UL, sub_trips.size()))
|
||||||
{
|
{
|
||||||
auto route = MakeRoute(
|
auto route = MakeRoute(sub_routes[index].segment_end_coordinates,
|
||||||
sub_routes[index].segment_end_coordinates, sub_routes[index].unpacked_path_segments,
|
sub_routes[index].unpacked_path_segments,
|
||||||
sub_routes[index].source_traversed_in_reverse,
|
sub_routes[index].source_traversed_in_reverse,
|
||||||
sub_routes[index].target_traversed_in_reverse);
|
sub_routes[index].target_traversed_in_reverse);
|
||||||
routes.values.push_back(std::move(route));
|
routes.values.push_back(std::move(route));
|
||||||
}
|
}
|
||||||
response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms);
|
response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms);
|
||||||
@@ -47,7 +47,9 @@ class TripAPI final : public RouteAPI
|
|||||||
response.values["code"] = "ok";
|
response.values["code"] = "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
|
||||||
|
// protected:
|
||||||
|
|
||||||
// FIXME this logic is a little backwards. We should change the output format of the
|
// FIXME this logic is a little backwards. We should change the output format of the
|
||||||
// trip plugin routing algorithm to be easier to consume here.
|
// trip plugin routing algorithm to be easier to consume here.
|
||||||
util::json::Array MakeWaypoints(const std::vector<std::vector<NodeID>> &sub_trips,
|
util::json::Array MakeWaypoints(const std::vector<std::vector<NodeID>> &sub_trips,
|
||||||
@@ -90,8 +92,7 @@ class TripAPI final : public RouteAPI
|
|||||||
auto trip_index = input_idx_to_trip_idx[input_index];
|
auto trip_index = input_idx_to_trip_idx[input_index];
|
||||||
BOOST_ASSERT(!trip_index.NotUsed());
|
BOOST_ASSERT(!trip_index.NotUsed());
|
||||||
|
|
||||||
auto waypoint =
|
auto waypoint = BaseAPI::MakeWaypoint(phantoms[input_index]);
|
||||||
BaseAPI::MakeWaypoint(parameters.coordinates[input_index], phantoms[input_index]);
|
|
||||||
waypoint.values["trips_index"] = trip_index.sub_trip_index;
|
waypoint.values["trips_index"] = trip_index.sub_trip_index;
|
||||||
waypoint.values["waypoint_index"] = trip_index.point_index;
|
waypoint.values["waypoint_index"] = trip_index.point_index;
|
||||||
waypoints.values.push_back(std::move(waypoint));
|
waypoints.values.push_back(std::move(waypoint));
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef OSRM_BASE64_HPP
|
||||||
|
#define OSRM_BASE64_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
|
||||||
|
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
|
||||||
|
// See: https://tools.ietf.org/html/rfc4648
|
||||||
|
// Implementation adapted from: http://stackoverflow.com/a/28471421
|
||||||
|
|
||||||
|
// The C++ standard guarantees none of this by default, but we need it in the following.
|
||||||
|
static_assert(CHAR_BIT == 8u, "we assume a byte holds 8 bits");
|
||||||
|
static_assert(sizeof(char) == 1u, "we assume a char is one byte large");
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
|
||||||
|
// Encoding Implementation
|
||||||
|
|
||||||
|
// Encodes a chunk of memory to Base64.
|
||||||
|
inline std::string encodeBase64(const unsigned char *first, std::size_t size)
|
||||||
|
{
|
||||||
|
using namespace boost::archive::iterators;
|
||||||
|
|
||||||
|
const std::string bytes{first, first + size};
|
||||||
|
|
||||||
|
using Iter = base64_from_binary<transform_width<std::string::const_iterator, 6, 8>>;
|
||||||
|
|
||||||
|
Iter view_first{begin(bytes)};
|
||||||
|
Iter view_last{end(bytes)};
|
||||||
|
|
||||||
|
std::string encoded{view_first, view_last};
|
||||||
|
|
||||||
|
return encoded.append((3 - size % 3) % 3, '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++11 standard 3.9.1/1: Plain char, signed char, and unsigned char are three distinct types
|
||||||
|
|
||||||
|
// Overload for signed char catches (not only but also) C-string literals.
|
||||||
|
inline std::string encodeBase64(const signed char *first, std::size_t size)
|
||||||
|
{
|
||||||
|
return encodeBase64(reinterpret_cast<const unsigned char *>(first), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload for char catches (not only but also) C-string literals.
|
||||||
|
inline std::string encodeBase64(const char *first, std::size_t size)
|
||||||
|
{
|
||||||
|
return encodeBase64(reinterpret_cast<const unsigned char *>(first), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience specialization, encoding from string instead of byte-dumping it.
|
||||||
|
inline std::string encodeBase64(const std::string &x) { return encodeBase64(x.data(), x.size()); }
|
||||||
|
|
||||||
|
// Encode any sufficiently trivial object to Base64.
|
||||||
|
template <typename T> std::string encodeBase64Bytewise(const T &x)
|
||||||
|
{
|
||||||
|
#if not defined __GNUC__ or __GNUC__ > 4
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return encodeBase64(reinterpret_cast<const unsigned char *>(&x), sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoding Implementation
|
||||||
|
|
||||||
|
// Decodes into a chunk of memory that is at least as large as the input.
|
||||||
|
template <typename OutputIter> void decodeBase64(const std::string &encoded, OutputIter out)
|
||||||
|
{
|
||||||
|
using namespace boost::archive::iterators;
|
||||||
|
using namespace boost::algorithm;
|
||||||
|
|
||||||
|
using Iter = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
|
||||||
|
|
||||||
|
Iter view_first{begin(encoded)};
|
||||||
|
Iter view_last{end(encoded)};
|
||||||
|
|
||||||
|
const auto null = [](const unsigned char c)
|
||||||
|
{
|
||||||
|
return c == '\0';
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto bytes = trim_right_copy_if(std::string{view_first, view_last}, null);
|
||||||
|
|
||||||
|
boost::copy(bytes, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience specialization, filling string instead of byte-dumping into it.
|
||||||
|
inline std::string decodeBase64(const std::string &encoded)
|
||||||
|
{
|
||||||
|
std::string rv;
|
||||||
|
|
||||||
|
decodeBase64(encoded, std::back_inserter(rv));
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodes from Base 64 to any sufficiently trivial object.
|
||||||
|
template <typename T> T decodeBase64Bytewise(const std::string &encoded)
|
||||||
|
{
|
||||||
|
#if not defined __GNUC__ or __GNUC__ > 4
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
T x;
|
||||||
|
|
||||||
|
decodeBase64(encoded, reinterpret_cast<unsigned char *>(&x));
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // ns engine
|
||||||
|
} // ns osrm
|
||||||
|
|
||||||
|
#endif /* OSRM_BASE64_HPP */
|
||||||
@@ -138,11 +138,13 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
|
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
|
||||||
|
|
||||||
virtual std::string get_name_for_id(const unsigned name_id) const = 0;
|
virtual std::string GetNameForID(const unsigned name_id) const = 0;
|
||||||
|
|
||||||
virtual std::size_t GetCoreSize() const = 0;
|
virtual std::size_t GetCoreSize() const = 0;
|
||||||
|
|
||||||
virtual std::string GetTimestamp() const = 0;
|
virtual std::string GetTimestamp() const = 0;
|
||||||
|
|
||||||
|
virtual bool GetUTurnsDefault() const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "engine/geospatial_query.hpp"
|
#include "engine/geospatial_query.hpp"
|
||||||
#include "extractor/original_edge_data.hpp"
|
#include "extractor/original_edge_data.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "contractor/query_edge.hpp"
|
#include "contractor/query_edge.hpp"
|
||||||
#include "util/shared_memory_vector_wrapper.hpp"
|
#include "util/shared_memory_vector_wrapper.hpp"
|
||||||
@@ -79,6 +80,7 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
util::ShM<unsigned, false>::vector m_segment_weights;
|
util::ShM<unsigned, false>::vector m_segment_weights;
|
||||||
util::ShM<uint8_t, false>::vector m_datasource_list;
|
util::ShM<uint8_t, false>::vector m_datasource_list;
|
||||||
util::ShM<std::string, false>::vector m_datasource_names;
|
util::ShM<std::string, false>::vector m_datasource_names;
|
||||||
|
extractor::ProfileProperties m_profile_properties;
|
||||||
|
|
||||||
boost::thread_specific_ptr<InternalRTree> m_static_rtree;
|
boost::thread_specific_ptr<InternalRTree> m_static_rtree;
|
||||||
boost::thread_specific_ptr<InternalGeospatialQuery> m_geospatial_query;
|
boost::thread_specific_ptr<InternalGeospatialQuery> m_geospatial_query;
|
||||||
@@ -86,26 +88,26 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
boost::filesystem::path file_index_path;
|
boost::filesystem::path file_index_path;
|
||||||
util::RangeTable<16, false> m_name_table;
|
util::RangeTable<16, false> m_name_table;
|
||||||
|
|
||||||
|
void LoadProfileProperties(const boost::filesystem::path &properties_path)
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream in_stream(properties_path);
|
||||||
|
if (!in_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + properties_path.string() + " for reading.");
|
||||||
|
}
|
||||||
|
|
||||||
|
in_stream.read(reinterpret_cast<char*>(&m_profile_properties), sizeof(m_profile_properties));
|
||||||
|
}
|
||||||
|
|
||||||
void LoadTimestamp(const boost::filesystem::path ×tamp_path)
|
void LoadTimestamp(const boost::filesystem::path ×tamp_path)
|
||||||
{
|
{
|
||||||
if (boost::filesystem::exists(timestamp_path))
|
util::SimpleLogger().Write() << "Loading Timestamp";
|
||||||
|
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
||||||
|
if (!timestamp_stream)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write() << "Loading Timestamp";
|
throw util::exception("Could not open " + timestamp_path.string() + " for reading.");
|
||||||
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
|
||||||
if (!timestamp_stream)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
|
|
||||||
}
|
|
||||||
getline(timestamp_stream, m_timestamp);
|
|
||||||
}
|
|
||||||
if (m_timestamp.empty())
|
|
||||||
{
|
|
||||||
m_timestamp = "n/a";
|
|
||||||
}
|
|
||||||
if (25 < m_timestamp.length())
|
|
||||||
{
|
|
||||||
m_timestamp.resize(25);
|
|
||||||
}
|
}
|
||||||
|
getline(timestamp_stream, m_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadGraph(const boost::filesystem::path &hsgr_path)
|
void LoadGraph(const boost::filesystem::path &hsgr_path)
|
||||||
@@ -218,28 +220,33 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
void LoadDatasourceInfo(const boost::filesystem::path &datasource_names_file,
|
void LoadDatasourceInfo(const boost::filesystem::path &datasource_names_file,
|
||||||
const boost::filesystem::path &datasource_indexes_file)
|
const boost::filesystem::path &datasource_indexes_file)
|
||||||
{
|
{
|
||||||
std::ifstream datasources_stream(datasource_indexes_file.c_str(), std::ios::binary);
|
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
|
||||||
if (datasources_stream)
|
if (!datasources_stream)
|
||||||
{
|
{
|
||||||
std::size_t number_of_datasources = 0;
|
throw util::exception("Could not open " + datasource_indexes_file.string() + " for reading!");
|
||||||
datasources_stream.read(reinterpret_cast<char *>(&number_of_datasources),
|
}
|
||||||
sizeof(std::size_t));
|
BOOST_ASSERT(datasources_stream);
|
||||||
if (number_of_datasources > 0)
|
|
||||||
{
|
std::size_t number_of_datasources = 0;
|
||||||
m_datasource_list.resize(number_of_datasources);
|
datasources_stream.read(reinterpret_cast<char *>(&number_of_datasources),
|
||||||
datasources_stream.read(reinterpret_cast<char *>(&(m_datasource_list[0])),
|
sizeof(std::size_t));
|
||||||
number_of_datasources * sizeof(uint8_t));
|
if (number_of_datasources > 0)
|
||||||
}
|
{
|
||||||
|
m_datasource_list.resize(number_of_datasources);
|
||||||
|
datasources_stream.read(reinterpret_cast<char *>(&(m_datasource_list[0])),
|
||||||
|
number_of_datasources * sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream datasourcenames_stream(datasource_names_file.c_str(), std::ios::binary);
|
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
|
||||||
if (datasourcenames_stream)
|
if (!datasourcenames_stream)
|
||||||
{
|
{
|
||||||
std::string name;
|
throw util::exception("Could not open " + datasource_names_file.string() + " for reading!");
|
||||||
while (std::getline(datasourcenames_stream, name))
|
}
|
||||||
{
|
BOOST_ASSERT(datasourcenames_stream);
|
||||||
m_datasource_names.push_back(name);
|
std::string name;
|
||||||
}
|
while (std::getline(datasourcenames_stream, name))
|
||||||
|
{
|
||||||
|
m_datasource_names.push_back(std::move(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,52 +283,35 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
m_geospatial_query.reset();
|
m_geospatial_query.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit InternalDataFacade(
|
explicit InternalDataFacade(const storage::StorageConfig& config)
|
||||||
const std::unordered_map<std::string, boost::filesystem::path> &server_paths)
|
|
||||||
{
|
{
|
||||||
// cache end iterator to quickly check .find against
|
ram_index_path = config.ram_index_path;
|
||||||
const auto end_it = end(server_paths);
|
file_index_path = config.file_index_path;
|
||||||
|
|
||||||
const auto file_for = [&server_paths, &end_it](const std::string &path)
|
|
||||||
{
|
|
||||||
const auto it = server_paths.find(path);
|
|
||||||
if (it == end_it || !boost::filesystem::is_regular_file(it->second))
|
|
||||||
throw util::exception("no valid " + path + " file given in ini file");
|
|
||||||
return it->second;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto optional_file_for = [&server_paths, &end_it](const std::string &path)
|
|
||||||
{
|
|
||||||
const auto it = server_paths.find(path);
|
|
||||||
if (it == end_it)
|
|
||||||
throw util::exception("no valid " + path + " file given in ini file");
|
|
||||||
return it->second;
|
|
||||||
};
|
|
||||||
|
|
||||||
ram_index_path = file_for("ramindex");
|
|
||||||
file_index_path = file_for("fileindex");
|
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading graph data";
|
util::SimpleLogger().Write() << "loading graph data";
|
||||||
LoadGraph(file_for("hsgrdata"));
|
LoadGraph(config.hsgr_data_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading edge information";
|
util::SimpleLogger().Write() << "loading edge information";
|
||||||
LoadNodeAndEdgeInformation(file_for("nodesdata"), file_for("edgesdata"));
|
LoadNodeAndEdgeInformation(config.nodes_data_path, config.edges_data_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading core information";
|
util::SimpleLogger().Write() << "loading core information";
|
||||||
LoadCoreInformation(file_for("coredata"));
|
LoadCoreInformation(config.core_data_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading geometries";
|
util::SimpleLogger().Write() << "loading geometries";
|
||||||
LoadGeometries(file_for("geometries"));
|
LoadGeometries(config.geometries_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading datasource info";
|
util::SimpleLogger().Write() << "loading datasource info";
|
||||||
LoadDatasourceInfo(optional_file_for("datasource_names"),
|
LoadDatasourceInfo(config.datasource_names_path,
|
||||||
optional_file_for("datasource_indexes"));
|
config.datasource_indexes_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading timestamp";
|
util::SimpleLogger().Write() << "loading timestamp";
|
||||||
LoadTimestamp(file_for("timestamp"));
|
LoadTimestamp(config.timestamp_path);
|
||||||
|
|
||||||
|
util::SimpleLogger().Write() << "loading profile properties";
|
||||||
|
LoadProfileProperties(config.properties_path);
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "loading street names";
|
util::SimpleLogger().Write() << "loading street names";
|
||||||
LoadStreetNames(file_for("namesdata"));
|
LoadStreetNames(config.names_data_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
@@ -551,7 +541,7 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
return m_name_ID_list.at(id);
|
return m_name_ID_list.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_name_for_id(const unsigned name_id) const override final
|
std::string GetNameForID(const unsigned name_id) const override final
|
||||||
{
|
{
|
||||||
if (std::numeric_limits<unsigned>::max() == name_id)
|
if (std::numeric_limits<unsigned>::max() == name_id)
|
||||||
{
|
{
|
||||||
@@ -652,16 +642,14 @@ class InternalDataFacade final : public BaseDataFacade
|
|||||||
|
|
||||||
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
|
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
|
||||||
{
|
{
|
||||||
if (m_datasource_names.empty() || datasource_name_id > m_datasource_names.size())
|
BOOST_ASSERT(m_datasource_names.size() >= 1);
|
||||||
{
|
BOOST_ASSERT(m_datasource_names.size() > datasource_name_id);
|
||||||
if (datasource_name_id == 0)
|
|
||||||
return "lua profile";
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
return m_datasource_names[datasource_name_id];
|
return m_datasource_names[datasource_name_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetTimestamp() const override final { return m_timestamp; }
|
std::string GetTimestamp() const override final { return m_timestamp; }
|
||||||
|
|
||||||
|
bool GetUTurnsDefault() const override final { return m_profile_properties.allow_u_turn_at_via; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "storage/shared_memory.hpp"
|
#include "storage/shared_memory.hpp"
|
||||||
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
|
|
||||||
#include "engine/geospatial_query.hpp"
|
#include "engine/geospatial_query.hpp"
|
||||||
#include "util/range_table.hpp"
|
#include "util/range_table.hpp"
|
||||||
@@ -68,6 +69,7 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
std::unique_ptr<storage::SharedMemory> m_layout_memory;
|
std::unique_ptr<storage::SharedMemory> m_layout_memory;
|
||||||
std::unique_ptr<storage::SharedMemory> m_large_memory;
|
std::unique_ptr<storage::SharedMemory> m_large_memory;
|
||||||
std::string m_timestamp;
|
std::string m_timestamp;
|
||||||
|
extractor::ProfileProperties* m_profile_properties;
|
||||||
|
|
||||||
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
|
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
|
||||||
util::ShM<NodeID, true>::vector m_via_node_list;
|
util::ShM<NodeID, true>::vector m_via_node_list;
|
||||||
@@ -98,6 +100,12 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
util::SimpleLogger().Write() << "set checksum: " << m_check_sum;
|
util::SimpleLogger().Write() << "set checksum: " << m_check_sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadProfileProperties()
|
||||||
|
{
|
||||||
|
m_profile_properties =
|
||||||
|
data_layout->GetBlockPtr<extractor::ProfileProperties>(shared_memory, storage::SharedDataLayout::PROPERTIES);
|
||||||
|
}
|
||||||
|
|
||||||
void LoadTimestamp()
|
void LoadTimestamp()
|
||||||
{
|
{
|
||||||
auto timestamp_ptr =
|
auto timestamp_ptr =
|
||||||
@@ -343,6 +351,7 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
LoadViaNodeList();
|
LoadViaNodeList();
|
||||||
LoadNames();
|
LoadNames();
|
||||||
LoadCoreInformation();
|
LoadCoreInformation();
|
||||||
|
LoadProfileProperties();
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "number of geometries: "
|
util::SimpleLogger().Write() << "number of geometries: "
|
||||||
<< m_coordinate_list->size();
|
<< m_coordinate_list->size();
|
||||||
@@ -621,7 +630,7 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
return m_name_ID_list.at(id);
|
return m_name_ID_list.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_name_for_id(const unsigned name_id) const override final
|
std::string GetNameForID(const unsigned name_id) const override final
|
||||||
{
|
{
|
||||||
if (std::numeric_limits<unsigned>::max() == name_id)
|
if (std::numeric_limits<unsigned>::max() == name_id)
|
||||||
{
|
{
|
||||||
@@ -684,16 +693,11 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
|
|
||||||
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
|
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(m_datasource_name_offsets.size() >= 1);
|
||||||
|
BOOST_ASSERT(m_datasource_name_offsets.size() > datasource_name_id);
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
|
result.reserve(m_datasource_name_lengths[datasource_name_id]);
|
||||||
if (m_datasource_name_offsets.empty() ||
|
|
||||||
datasource_name_id > m_datasource_name_offsets.size())
|
|
||||||
{
|
|
||||||
if (datasource_name_id == 0)
|
|
||||||
return "lua profile";
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::copy(m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id],
|
std::copy(m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id],
|
||||||
m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id] +
|
m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id] +
|
||||||
m_datasource_name_lengths[datasource_name_id],
|
m_datasource_name_lengths[datasource_name_id],
|
||||||
@@ -703,6 +707,8 @@ class SharedDataFacade final : public BaseDataFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetTimestamp() const override final { return m_timestamp; }
|
std::string GetTimestamp() const override final { return m_timestamp; }
|
||||||
|
|
||||||
|
bool GetUTurnsDefault() const override final { return m_profile_properties->allow_u_turn_at_via; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef ENGINE_CONFIG_HPP
|
#ifndef ENGINE_CONFIG_HPP
|
||||||
#define ENGINE_CONFIG_HPP
|
#define ENGINE_CONFIG_HPP
|
||||||
|
|
||||||
|
#include "storage/storage_config.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -41,24 +42,9 @@ namespace engine
|
|||||||
|
|
||||||
struct EngineConfig
|
struct EngineConfig
|
||||||
{
|
{
|
||||||
EngineConfig() = default;
|
bool IsValid() const;
|
||||||
|
|
||||||
EngineConfig(const boost::filesystem::path &base)
|
storage::StorageConfig storage_config;
|
||||||
: server_paths{{"ramindex", base.string() + ".ramIndex"},
|
|
||||||
{"fileindex", base.string() + ".fileIndex"},
|
|
||||||
{"hsgrdata", base.string() + ".hsgr"},
|
|
||||||
{"nodesdata", base.string() + ".nodes"},
|
|
||||||
{"edgesdata", base.string() + ".edges"},
|
|
||||||
{"coredata", base.string() + ".core"},
|
|
||||||
{"geometries", base.string() + ".geometry"},
|
|
||||||
{"timestamp", base.string() + ".timestamp"},
|
|
||||||
{"datasource_names", base.string() + ".datasource_names"},
|
|
||||||
{"datasource_indexes", base.string() + ".datasource_indexes"},
|
|
||||||
{"namesdata", base.string() + ".names"}}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unordered_map<std::string, boost::filesystem::path> server_paths;
|
|
||||||
int max_locations_trip = -1;
|
int max_locations_trip = -1;
|
||||||
int max_locations_viaroute = -1;
|
int max_locations_viaroute = -1;
|
||||||
int max_locations_distance_table = -1;
|
int max_locations_distance_table = -1;
|
||||||
|
|||||||
@@ -244,8 +244,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, bearing, bearing_range, &has_big_component,
|
[this, bearing, bearing_range, &has_big_component, &has_small_component](
|
||||||
&has_small_component](const EdgeData &data)
|
const EdgeData &data)
|
||||||
{
|
{
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !data.component.is_tiny));
|
(!has_small_component || (!has_big_component && !data.component.is_tiny));
|
||||||
@@ -290,8 +290,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, bearing, bearing_range, &has_big_component,
|
[this, bearing, bearing_range, &has_big_component, &has_small_component](
|
||||||
&has_small_component](const EdgeData &data)
|
const EdgeData &data)
|
||||||
{
|
{
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !data.component.is_tiny));
|
(!has_small_component || (!has_big_component && !data.component.is_tiny));
|
||||||
@@ -393,10 +393,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_weight *= 1.0 - ratio;
|
reverse_weight *= 1.0 - ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto transformed =
|
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
||||||
PhantomNodeWithDistance{PhantomNode{data, forward_weight, forward_offset,
|
forward_weight,
|
||||||
reverse_weight, reverse_offset, point_on_segment},
|
forward_offset,
|
||||||
current_perpendicular_distance};
|
reverse_weight,
|
||||||
|
reverse_offset,
|
||||||
|
point_on_segment,
|
||||||
|
input_coordinate},
|
||||||
|
current_perpendicular_distance};
|
||||||
|
|
||||||
return transformed;
|
return transformed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
|
|||||||
current_distance +=
|
current_distance +=
|
||||||
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
|
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
|
||||||
|
|
||||||
if (!isSilent(path_point.turn_instruction))
|
// all changes to this check have to be matched with assemble_steps
|
||||||
|
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
||||||
{
|
{
|
||||||
geometry.segment_distances.push_back(current_distance);
|
geometry.segment_distances.push_back(current_distance);
|
||||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||||
|
|||||||
@@ -96,18 +96,12 @@ template <typename DataFacadeT>
|
|||||||
RouteLeg assembleLeg(const DataFacadeT &facade,
|
RouteLeg assembleLeg(const DataFacadeT &facade,
|
||||||
const std::vector<PathData> &route_data,
|
const std::vector<PathData> &route_data,
|
||||||
const LegGeometry &leg_geometry,
|
const LegGeometry &leg_geometry,
|
||||||
const PhantomNode &source_node,
|
|
||||||
const PhantomNode &target_node,
|
const PhantomNode &target_node,
|
||||||
const bool source_traversed_in_reverse,
|
|
||||||
const bool target_traversed_in_reverse)
|
const bool target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
const auto source_duration =
|
|
||||||
(source_traversed_in_reverse ? source_node.GetReverseWeightPlusOffset()
|
|
||||||
: source_node.GetForwardWeightPlusOffset()) /
|
|
||||||
10.;
|
|
||||||
const auto target_duration =
|
const auto target_duration =
|
||||||
(target_traversed_in_reverse ? target_node.GetReverseWeightPlusOffset()
|
(target_traversed_in_reverse ? target_node.reverse_weight
|
||||||
: target_node.GetForwardWeightPlusOffset()) /
|
: target_node.forward_weight) /
|
||||||
10.;
|
10.;
|
||||||
|
|
||||||
auto distance = std::accumulate(leg_geometry.segment_distances.begin(),
|
auto distance = std::accumulate(leg_geometry.segment_distances.begin(),
|
||||||
@@ -136,25 +130,21 @@ RouteLeg assembleLeg(const DataFacadeT &facade,
|
|||||||
// The phantom node of t will contain:
|
// The phantom node of t will contain:
|
||||||
// `forward_weight`: duration of (d,t)
|
// `forward_weight`: duration of (d,t)
|
||||||
// `forward_offset`: duration of (c, d)
|
// `forward_offset`: duration of (c, d)
|
||||||
//
|
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
|
||||||
// TODO discuss, this should not be the case after danpats fixes
|
// caputed by the phantom node. So we need to add the target duration here.
|
||||||
// The PathData will contain entries of b, c and d. But only c will contain
|
duration = duration + target_duration;
|
||||||
// a duration value since its the only point associated with a turn.
|
|
||||||
// As such we want to slice of the duration for (a,s) and add the duration for
|
|
||||||
// (c,d,t)
|
|
||||||
duration = duration - source_duration + target_duration;
|
|
||||||
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(route_data);
|
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(route_data);
|
||||||
|
|
||||||
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
|
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
|
||||||
BOOST_ASSERT(summary_array.begin() != summary_array.end());
|
BOOST_ASSERT(summary_array.begin() != summary_array.end());
|
||||||
std::string summary =
|
std::string summary =
|
||||||
std::accumulate(std::next(summary_array.begin()), summary_array.end(),
|
std::accumulate(std::next(summary_array.begin()), summary_array.end(),
|
||||||
facade.get_name_for_id(summary_array.front()),
|
facade.GetNameForID(summary_array.front()),
|
||||||
[&facade](std::string previous, const std::uint32_t name_id)
|
[&facade](std::string previous, const std::uint32_t name_id)
|
||||||
{
|
{
|
||||||
if (name_id != 0)
|
if (name_id != 0)
|
||||||
{
|
{
|
||||||
previous += ", " + facade.get_name_for_id(name_id);
|
previous += ", " + facade.GetNameForID(name_id);
|
||||||
}
|
}
|
||||||
return previous;
|
return previous;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ namespace guidance
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||||
const WaypointType waypoint_type,
|
|
||||||
const LegGeometry &leg_geometry,
|
const LegGeometry &leg_geometry,
|
||||||
const std::size_t segment_index,
|
const std::size_t segment_index);
|
||||||
const unsigned exit);
|
|
||||||
|
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||||
|
const WaypointType waypoint_type,
|
||||||
|
const LegGeometry &leg_geometry);
|
||||||
|
|
||||||
} // ns detail
|
} // ns detail
|
||||||
|
|
||||||
template <typename DataFacadeT>
|
template <typename DataFacadeT>
|
||||||
@@ -40,13 +43,14 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
const bool source_traversed_in_reverse,
|
const bool source_traversed_in_reverse,
|
||||||
const bool target_traversed_in_reverse)
|
const bool target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
|
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.;
|
||||||
const EdgeWeight source_duration =
|
const EdgeWeight source_duration =
|
||||||
source_traversed_in_reverse ? source_node.forward_weight : source_node.reverse_weight;
|
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
|
||||||
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
||||||
: source_node.forward_travel_mode;
|
: source_node.forward_travel_mode;
|
||||||
|
|
||||||
const EdgeWeight target_duration =
|
const EdgeWeight target_duration =
|
||||||
target_traversed_in_reverse ? target_node.forward_weight : target_node.reverse_weight;
|
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
||||||
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
|
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
|
||||||
: target_node.forward_travel_mode;
|
: target_node.forward_travel_mode;
|
||||||
|
|
||||||
@@ -56,10 +60,18 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
steps.reserve(number_of_segments);
|
steps.reserve(number_of_segments);
|
||||||
|
|
||||||
std::size_t segment_index = 0;
|
std::size_t segment_index = 0;
|
||||||
|
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||||
|
|
||||||
|
// We report the relative position of source/target to the road only within a range that is
|
||||||
|
// sufficiently different but not full of the path
|
||||||
|
const constexpr double MINIMAL_RELATIVE_DISTANCE = 5., MAXIMAL_RELATIVE_DISTANCE = 300.;
|
||||||
|
const auto distance_to_start = util::coordinate_calculation::haversineDistance(
|
||||||
|
source_node.input_location, leg_geometry.locations[0]);
|
||||||
const auto initial_modifier =
|
const auto initial_modifier =
|
||||||
leg_geometry.locations.size() >= 3
|
distance_to_start >= MINIMAL_RELATIVE_DISTANCE &&
|
||||||
|
distance_to_start <= MAXIMAL_RELATIVE_DISTANCE
|
||||||
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
|
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
|
||||||
leg_geometry.locations[0], leg_geometry.locations[1], leg_geometry.locations[2]))
|
source_node.input_location, leg_geometry.locations[0], leg_geometry.locations[1]))
|
||||||
: extractor::guidance::DirectionModifier::UTurn;
|
: extractor::guidance::DirectionModifier::UTurn;
|
||||||
|
|
||||||
if (leg_data.size() > 0)
|
if (leg_data.size() > 0)
|
||||||
@@ -68,7 +80,8 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
StepManeuver maneuver = detail::stepManeuverFromGeometry(
|
StepManeuver maneuver = detail::stepManeuverFromGeometry(
|
||||||
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
|
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
|
||||||
initial_modifier},
|
initial_modifier},
|
||||||
WaypointType::Depart, leg_geometry, segment_index, INVALID_EXIT_NR);
|
WaypointType::Depart, leg_geometry);
|
||||||
|
maneuver.location = source_node.location;
|
||||||
|
|
||||||
// PathData saves the information we need of the segment _before_ the turn,
|
// PathData saves the information we need of the segment _before_ the turn,
|
||||||
// but a RouteStep is with regard to the segment after the turn.
|
// but a RouteStep is with regard to the segment after the turn.
|
||||||
@@ -79,18 +92,22 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
{
|
{
|
||||||
segment_duration += path_point.duration_until_turn;
|
segment_duration += path_point.duration_until_turn;
|
||||||
|
|
||||||
if (path_point.turn_instruction != extractor::guidance::TurnInstruction::NO_TURN())
|
// all changes to this check have to be matched with assemble_geometry
|
||||||
|
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(segment_duration >= 0);
|
BOOST_ASSERT(segment_duration >= 0);
|
||||||
const auto name = facade.get_name_for_id(path_point.name_id);
|
const auto name = facade.GetNameForID(path_point.name_id);
|
||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
steps.push_back(RouteStep{path_point.name_id, name, segment_duration / 10.0,
|
steps.push_back(RouteStep{path_point.name_id,
|
||||||
distance, path_point.travel_mode, maneuver,
|
name,
|
||||||
|
segment_duration / 10.0,
|
||||||
|
distance,
|
||||||
|
path_point.travel_mode,
|
||||||
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1});
|
leg_geometry.BackIndex(segment_index) + 1});
|
||||||
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
|
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
|
||||||
WaypointType::None, leg_geometry,
|
leg_geometry, segment_index);
|
||||||
segment_index, path_point.exit);
|
|
||||||
segment_index++;
|
segment_index++;
|
||||||
segment_duration = 0;
|
segment_duration = 0;
|
||||||
}
|
}
|
||||||
@@ -98,8 +115,12 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
const int duration = segment_duration + target_duration;
|
const int duration = segment_duration + target_duration;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id),
|
steps.push_back(RouteStep{target_node.name_id,
|
||||||
duration / 10., distance, target_mode, maneuver,
|
facade.GetNameForID(target_node.name_id),
|
||||||
|
duration / 10.,
|
||||||
|
distance,
|
||||||
|
target_mode,
|
||||||
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1});
|
leg_geometry.BackIndex(segment_index) + 1});
|
||||||
}
|
}
|
||||||
@@ -112,35 +133,46 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
// |---| source_duration
|
// |---| source_duration
|
||||||
// |---------| target_duration
|
// |---------| target_duration
|
||||||
|
|
||||||
StepManeuver maneuver = {source_node.location, 0., 0.,
|
StepManeuver maneuver = detail::stepManeuverFromGeometry(
|
||||||
extractor::guidance::TurnInstruction{
|
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
|
||||||
extractor::guidance::TurnType::NoTurn, initial_modifier},
|
initial_modifier},
|
||||||
WaypointType::Depart, INVALID_EXIT_NR};
|
WaypointType::Depart, leg_geometry);
|
||||||
int duration = target_duration - source_duration;
|
int duration = target_duration - source_duration;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
|
|
||||||
steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id),
|
steps.push_back(RouteStep{source_node.name_id,
|
||||||
duration / 10., leg_geometry.segment_distances[segment_index], source_mode,
|
facade.GetNameForID(source_node.name_id),
|
||||||
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
|
duration / 10.,
|
||||||
|
leg_geometry.segment_distances[segment_index],
|
||||||
|
source_mode,
|
||||||
|
std::move(maneuver),
|
||||||
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1});
|
leg_geometry.BackIndex(segment_index) + 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||||
|
const auto distance_from_end = util::coordinate_calculation::haversineDistance(
|
||||||
|
target_node.input_location, leg_geometry.locations.back());
|
||||||
const auto final_modifier =
|
const auto final_modifier =
|
||||||
leg_geometry.locations.size() >= 3
|
distance_from_end >= MINIMAL_RELATIVE_DISTANCE &&
|
||||||
|
distance_from_end <= MAXIMAL_RELATIVE_DISTANCE
|
||||||
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
|
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
|
||||||
leg_geometry.locations[leg_geometry.locations.size() - 3],
|
|
||||||
leg_geometry.locations[leg_geometry.locations.size() - 2],
|
leg_geometry.locations[leg_geometry.locations.size() - 2],
|
||||||
leg_geometry.locations[leg_geometry.locations.size() - 1]))
|
leg_geometry.locations[leg_geometry.locations.size() - 1],
|
||||||
|
target_node.input_location))
|
||||||
: extractor::guidance::DirectionModifier::UTurn;
|
: extractor::guidance::DirectionModifier::UTurn;
|
||||||
// This step has length zero, the only reason we need it is the target location
|
// This step has length zero, the only reason we need it is the target location
|
||||||
steps.push_back(RouteStep{
|
auto final_maneuver = detail::stepManeuverFromGeometry(
|
||||||
target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode,
|
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn, final_modifier},
|
||||||
StepManeuver{target_node.location, 0., 0.,
|
WaypointType::Arrive, leg_geometry);
|
||||||
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
|
steps.push_back(RouteStep{target_node.name_id,
|
||||||
final_modifier},
|
facade.GetNameForID(target_node.name_id),
|
||||||
WaypointType::Arrive, INVALID_EXIT_NR},
|
ZERO_DURATION,
|
||||||
leg_geometry.locations.size(), leg_geometry.locations.size()});
|
ZERO_DISTANCE,
|
||||||
|
target_mode,
|
||||||
|
final_maneuver,
|
||||||
|
leg_geometry.locations.size(),
|
||||||
|
leg_geometry.locations.size()});
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#ifndef ENGINE_GUIDANCE_POST_PROCESSING_HPP
|
#ifndef ENGINE_GUIDANCE_POST_PROCESSING_HPP
|
||||||
#define ENGINE_GUIDANCE_POST_PROCESSING_HPP
|
#define ENGINE_GUIDANCE_POST_PROCESSING_HPP
|
||||||
|
|
||||||
#include "engine/internal_route_result.hpp"
|
#include "engine/guidance/route_step.hpp"
|
||||||
|
#include "engine/guidance/leg_geometry.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -12,7 +13,15 @@ namespace engine
|
|||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> path_data);
|
// passed as none-reference to modify in-place and move out again
|
||||||
|
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
|
// postProcess will break the connection between the leg geometry
|
||||||
|
// for which a segment is supposed to represent exactly the coordinates
|
||||||
|
// between routing maneuvers and the route steps itself.
|
||||||
|
// If required, we can get both in sync again using this function.
|
||||||
|
// Move in LegGeometry for modification in place.
|
||||||
|
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps);
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,14 @@ enum class WaypointType : std::uint8_t
|
|||||||
Depart,
|
Depart,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//A represenetation of intermediate intersections
|
||||||
|
struct IntermediateIntersection
|
||||||
|
{
|
||||||
|
double duration;
|
||||||
|
double distance;
|
||||||
|
util::Coordinate location;
|
||||||
|
};
|
||||||
|
|
||||||
struct StepManeuver
|
struct StepManeuver
|
||||||
{
|
{
|
||||||
util::Coordinate location;
|
util::Coordinate location;
|
||||||
@@ -28,6 +37,7 @@ struct StepManeuver
|
|||||||
extractor::guidance::TurnInstruction instruction;
|
extractor::guidance::TurnInstruction instruction;
|
||||||
WaypointType waypoint_type;
|
WaypointType waypoint_type;
|
||||||
unsigned exit;
|
unsigned exit;
|
||||||
|
std::vector<IntermediateIntersection> intersections;
|
||||||
};
|
};
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|||||||
+15
-10
@@ -34,39 +34,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Fwd. decls.
|
||||||
|
namespace datafacade
|
||||||
|
{
|
||||||
|
struct BaseDataFacade;
|
||||||
|
}
|
||||||
|
|
||||||
// Is returned as a temporary identifier for snapped coodinates
|
// Is returned as a temporary identifier for snapped coodinates
|
||||||
struct Hint
|
struct Hint
|
||||||
{
|
{
|
||||||
util::Coordinate input_coordinate;
|
|
||||||
PhantomNode phantom;
|
PhantomNode phantom;
|
||||||
std::uint32_t data_checksum;
|
std::uint32_t data_checksum;
|
||||||
|
|
||||||
template <typename DataFacadeT>
|
bool IsValid(const util::Coordinate new_input_coordinates,
|
||||||
bool IsValid(const util::Coordinate new_input_coordinates, DataFacadeT &facade) const
|
const datafacade::BaseDataFacade &facade) const;
|
||||||
{
|
|
||||||
auto is_same_input_coordinate = new_input_coordinates.lon == input_coordinate.lon &&
|
|
||||||
new_input_coordinates.lat == input_coordinate.lat;
|
|
||||||
return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) &&
|
|
||||||
facade.GetCheckSum() == data_checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToBase64() const;
|
std::string ToBase64() const;
|
||||||
static Hint FromBase64(const std::string &base64Hint);
|
static Hint FromBase64(const std::string &base64Hint);
|
||||||
|
|
||||||
|
friend bool operator==(const Hint &, const Hint &);
|
||||||
|
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
static_assert(sizeof(Hint) == 60 + 4, "Hint is bigger than expected");
|
||||||
constexpr std::size_t ENCODED_HINT_SIZE = 88;
|
constexpr std::size_t ENCODED_HINT_SIZE = 88;
|
||||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||||
#else
|
#else
|
||||||
// PhantomNode is bigger under windows because MSVC does not support bit packing
|
// PhantomNode is bigger under windows because MSVC does not support bit packing
|
||||||
constexpr std::size_t ENCODED_HINT_SIZE = 84;
|
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
|
||||||
|
constexpr std::size_t ENCODED_HINT_SIZE = 92;
|
||||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ struct PathData
|
|||||||
extractor::guidance::TurnInstruction turn_instruction;
|
extractor::guidance::TurnInstruction turn_instruction;
|
||||||
// travel mode of the street that leads to the turn
|
// travel mode of the street that leads to the turn
|
||||||
extractor::TravelMode travel_mode : 4;
|
extractor::TravelMode travel_mode : 4;
|
||||||
// exit ID of highway exit, roundabout exit, intersection nr
|
|
||||||
unsigned exit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InternalRouteResult
|
struct InternalRouteResult
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
#ifndef OBJECT_ENCODER_HPP
|
|
||||||
#define OBJECT_ENCODER_HPP
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
static_assert(CHAR_BIT == 8u, "we assume a byte holds 8 bits");
|
|
||||||
static_assert(sizeof(char) == 1u, "we assume a char is one byte large");
|
|
||||||
|
|
||||||
using Base64FromBinary = boost::archive::iterators::base64_from_binary<
|
|
||||||
boost::archive::iterators::transform_width<const char *, // sequence of chars
|
|
||||||
6, // get view of 6 bit
|
|
||||||
8 // from sequence of 8 bit
|
|
||||||
>>;
|
|
||||||
|
|
||||||
using BinaryFromBase64 = boost::archive::iterators::transform_width<
|
|
||||||
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
|
|
||||||
8, // get a view of 8 bit
|
|
||||||
6 // from a sequence of 6 bit
|
|
||||||
>;
|
|
||||||
} // ns detail
|
|
||||||
|
|
||||||
template <typename T> std::string encodeBase64(const T &x)
|
|
||||||
{
|
|
||||||
#if not defined __GNUC__ or __GNUC__ > 4
|
|
||||||
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<unsigned char> bytes{reinterpret_cast<const char *>(&x),
|
|
||||||
reinterpret_cast<const char *>(&x) + sizeof(T)};
|
|
||||||
BOOST_ASSERT(!bytes.empty());
|
|
||||||
|
|
||||||
std::size_t bytes_to_pad{0};
|
|
||||||
|
|
||||||
while (bytes.size() % 3 != 0)
|
|
||||||
{
|
|
||||||
bytes_to_pad += 1;
|
|
||||||
bytes.push_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(bytes_to_pad == 0 || bytes_to_pad == 1 || bytes_to_pad == 2);
|
|
||||||
BOOST_ASSERT_MSG(0 == bytes.size() % 3, "base64 input data size is not a multiple of 3");
|
|
||||||
|
|
||||||
std::string encoded{detail::Base64FromBinary{bytes.data()},
|
|
||||||
detail::Base64FromBinary{bytes.data() + (bytes.size() - bytes_to_pad)}};
|
|
||||||
|
|
||||||
std::replace(begin(encoded), end(encoded), '+', '-');
|
|
||||||
std::replace(begin(encoded), end(encoded), '/', '_');
|
|
||||||
|
|
||||||
return encoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> T decodeBase64(std::string encoded)
|
|
||||||
{
|
|
||||||
#if not defined __GNUC__ or __GNUC__ > 4
|
|
||||||
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::replace(begin(encoded), end(encoded), '-', '+');
|
|
||||||
std::replace(begin(encoded), end(encoded), '_', '/');
|
|
||||||
|
|
||||||
T rv;
|
|
||||||
|
|
||||||
std::copy(detail::BinaryFromBase64{begin(encoded)},
|
|
||||||
detail::BinaryFromBase64{begin(encoded) + encoded.length()},
|
|
||||||
reinterpret_cast<char *>(&rv));
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // ns engine
|
|
||||||
} // ns osrm
|
|
||||||
|
|
||||||
#endif /* OBJECT_ENCODER_HPP */
|
|
||||||
@@ -56,6 +56,7 @@ struct PhantomNode
|
|||||||
bool is_tiny_component,
|
bool is_tiny_component,
|
||||||
unsigned component_id,
|
unsigned component_id,
|
||||||
util::Coordinate location,
|
util::Coordinate location,
|
||||||
|
util::Coordinate input_location,
|
||||||
unsigned short fwd_segment_position,
|
unsigned short fwd_segment_position,
|
||||||
extractor::TravelMode forward_travel_mode,
|
extractor::TravelMode forward_travel_mode,
|
||||||
extractor::TravelMode backward_travel_mode)
|
extractor::TravelMode backward_travel_mode)
|
||||||
@@ -65,8 +66,8 @@ struct PhantomNode
|
|||||||
forward_packed_geometry_id(forward_packed_geometry_id_),
|
forward_packed_geometry_id(forward_packed_geometry_id_),
|
||||||
reverse_packed_geometry_id(reverse_packed_geometry_id_),
|
reverse_packed_geometry_id(reverse_packed_geometry_id_),
|
||||||
component{component_id, is_tiny_component}, location(std::move(location)),
|
component{component_id, is_tiny_component}, location(std::move(location)),
|
||||||
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
|
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
|
||||||
backward_travel_mode(backward_travel_mode)
|
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +116,11 @@ struct PhantomNode
|
|||||||
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
|
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsValid(const unsigned number_of_nodes, const util::Coordinate queried_coordinate) const
|
||||||
|
{
|
||||||
|
return queried_coordinate == input_location && IsValid(number_of_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
||||||
|
|
||||||
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
||||||
@@ -125,7 +131,8 @@ struct PhantomNode
|
|||||||
int forward_offset_,
|
int forward_offset_,
|
||||||
int reverse_weight_,
|
int reverse_weight_,
|
||||||
int reverse_offset_,
|
int reverse_offset_,
|
||||||
const util::Coordinate foot_point)
|
const util::Coordinate location_,
|
||||||
|
const util::Coordinate input_location_)
|
||||||
{
|
{
|
||||||
forward_node_id = other.forward_edge_based_node_id;
|
forward_node_id = other.forward_edge_based_node_id;
|
||||||
reverse_node_id = other.reverse_edge_based_node_id;
|
reverse_node_id = other.reverse_edge_based_node_id;
|
||||||
@@ -143,7 +150,8 @@ struct PhantomNode
|
|||||||
component.id = other.component.id;
|
component.id = other.component.id;
|
||||||
component.is_tiny = other.component.is_tiny;
|
component.is_tiny = other.component.is_tiny;
|
||||||
|
|
||||||
location = foot_point;
|
location = location_;
|
||||||
|
input_location = input_location_;
|
||||||
fwd_segment_position = other.fwd_segment_position;
|
fwd_segment_position = other.fwd_segment_position;
|
||||||
|
|
||||||
forward_travel_mode = other.forward_travel_mode;
|
forward_travel_mode = other.forward_travel_mode;
|
||||||
@@ -169,6 +177,7 @@ struct PhantomNode
|
|||||||
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big");
|
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big");
|
||||||
#endif
|
#endif
|
||||||
util::Coordinate location;
|
util::Coordinate location;
|
||||||
|
util::Coordinate input_location;
|
||||||
unsigned short fwd_segment_position;
|
unsigned short fwd_segment_position;
|
||||||
// note 4 bits would suffice for each,
|
// note 4 bits would suffice for each,
|
||||||
// but the saved byte would be padding anyway
|
// but the saved byte would be padding anyway
|
||||||
@@ -177,7 +186,9 @@ struct PhantomNode
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
static_assert(sizeof(PhantomNode) == 52, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected");
|
||||||
|
#else
|
||||||
|
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "engine/plugins/plugin_base.hpp"
|
#include "engine/plugins/plugin_base.hpp"
|
||||||
#include "engine/api/route_api.hpp"
|
#include "engine/api/route_api.hpp"
|
||||||
|
|
||||||
#include "engine/object_encoder.hpp"
|
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
#include "engine/routing_algorithms/shortest_path.hpp"
|
#include "engine/routing_algorithms/shortest_path.hpp"
|
||||||
#include "engine/routing_algorithms/alternative_path.hpp"
|
#include "engine/routing_algorithms/alternative_path.hpp"
|
||||||
|
|||||||
@@ -299,8 +299,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
weight_vector);
|
weight_vector);
|
||||||
BOOST_ASSERT(weight_vector.size() > 0);
|
BOOST_ASSERT(weight_vector.size() > 0);
|
||||||
|
|
||||||
auto total_weight =
|
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
||||||
std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
|
||||||
|
|
||||||
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
||||||
// ed.distance should be total_weight + penalties (turn, stop, etc)
|
// ed.distance should be total_weight + penalties (turn, stop, etc)
|
||||||
@@ -322,14 +321,17 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
{
|
{
|
||||||
unpacked_path.push_back(
|
unpacked_path.push_back(
|
||||||
PathData{id_vector[i], name_index, weight_vector[i],
|
PathData{id_vector[i], name_index, weight_vector[i],
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode,
|
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode});
|
||||||
INVALID_EXIT_NR});
|
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||||
unpacked_path.back().turn_instruction = turn_instruction;
|
unpacked_path.back().turn_instruction = turn_instruction;
|
||||||
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
|
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
|
||||||
|
|
||||||
if (is_first_segment)
|
if (is_first_segment)
|
||||||
{
|
{
|
||||||
|
auto source_weight = start_traversed_in_reverse
|
||||||
|
? phantom_node_pair.source_phantom.reverse_weight
|
||||||
|
: phantom_node_pair.source_phantom.forward_weight;
|
||||||
// Given this geometry:
|
// Given this geometry:
|
||||||
// U---v---w---x---Z
|
// U---v---w---x---Z
|
||||||
// s
|
// s
|
||||||
@@ -337,12 +339,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
// However the first segment duration needs to be adjusted to the fact that the
|
// However the first segment duration needs to be adjusted to the fact that the
|
||||||
// source phantom is in the middle of the segment.
|
// source phantom is in the middle of the segment.
|
||||||
// We do this by subtracting v--s from the duration.
|
// We do this by subtracting v--s from the duration.
|
||||||
BOOST_ASSERT(unpacked_path.front().duration_until_turn >=
|
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
|
||||||
phantom_node_pair.source_phantom.forward_weight);
|
unpacked_path.front().duration_until_turn -= source_weight;
|
||||||
unpacked_path.front().duration_until_turn -=
|
|
||||||
start_traversed_in_reverse
|
|
||||||
? phantom_node_pair.source_phantom.forward_weight
|
|
||||||
: phantom_node_pair.source_phantom.reverse_weight;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,7 +386,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
// s: fwd_segment 0
|
// s: fwd_segment 0
|
||||||
// t: fwd_segment 3
|
// t: fwd_segment 3
|
||||||
// -> (U, v), (v, w), (w, x)
|
// -> (U, v), (v, w), (w, x)
|
||||||
// note that (x, t) is _not_ included but needs to
|
// note that (x, t) is _not_ included but needs to be added later.
|
||||||
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
|
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(i < id_vector.size());
|
BOOST_ASSERT(i < id_vector.size());
|
||||||
@@ -397,20 +395,20 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
|||||||
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
|
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||||
: phantom_node_pair.target_phantom.forward_travel_mode,
|
: phantom_node_pair.target_phantom.forward_travel_mode});
|
||||||
INVALID_EXIT_NR});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_local_path && unpacked_path.size() > 0)
|
if (is_local_path && unpacked_path.size() > 0)
|
||||||
{
|
{
|
||||||
|
auto source_weight = start_traversed_in_reverse
|
||||||
|
? phantom_node_pair.source_phantom.reverse_weight
|
||||||
|
: phantom_node_pair.source_phantom.forward_weight;
|
||||||
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
|
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
|
||||||
// However the first segment duration needs to be adjusted to the fact that the source
|
// However the first segment duration needs to be adjusted to the fact that the source
|
||||||
// phantom
|
// phantom is in the middle of the segment. We do this by subtracting v--s from the
|
||||||
// is in the middle of the segment. We do this by subtracting v--s from the duration.
|
// duration.
|
||||||
BOOST_ASSERT(unpacked_path.front().duration_until_turn >=
|
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
|
||||||
phantom_node_pair.source_phantom.forward_weight);
|
unpacked_path.front().duration_until_turn -= source_weight;
|
||||||
unpacked_path.front().duration_until_turn -=
|
|
||||||
phantom_node_pair.source_phantom.forward_weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is no equivalent to a node-based node in an edge-expanded graph.
|
// there is no equivalent to a node-based node in an edge-expanded graph.
|
||||||
|
|||||||
@@ -237,14 +237,10 @@ class ShortestPathRouting final
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const constexpr bool UTURN_DEFAULT = false;
|
|
||||||
|
|
||||||
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const std::vector<boost::optional<bool>> &uturn_indicators,
|
const boost::optional<bool> uturns,
|
||||||
InternalRouteResult &raw_route_data) const
|
InternalRouteResult &raw_route_data) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(uturn_indicators.empty() ||
|
|
||||||
uturn_indicators.size() == phantom_nodes_vector.size() + 1);
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::facade->GetNumberOfNodes());
|
super::facade->GetNumberOfNodes());
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
@@ -270,7 +266,7 @@ class ShortestPathRouting final
|
|||||||
std::vector<NodeID> total_packed_path_to_reverse;
|
std::vector<NodeID> total_packed_path_to_reverse;
|
||||||
std::vector<std::size_t> packed_leg_to_reverse_begin;
|
std::vector<std::size_t> packed_leg_to_reverse_begin;
|
||||||
|
|
||||||
const bool use_uturn_indicators = !uturn_indicators.empty();
|
const bool allow_u_turn_at_via = uturns ? *uturns : super::facade->GetUTurnsDefault();
|
||||||
|
|
||||||
std::size_t current_leg = 0;
|
std::size_t current_leg = 0;
|
||||||
// this implements a dynamic program that finds the shortest route through
|
// this implements a dynamic program that finds the shortest route through
|
||||||
@@ -286,12 +282,6 @@ class ShortestPathRouting final
|
|||||||
const auto &source_phantom = phantom_node_pair.source_phantom;
|
const auto &source_phantom = phantom_node_pair.source_phantom;
|
||||||
const auto &target_phantom = phantom_node_pair.target_phantom;
|
const auto &target_phantom = phantom_node_pair.target_phantom;
|
||||||
|
|
||||||
const bool use_uturn_default =
|
|
||||||
!use_uturn_indicators || !uturn_indicators[current_leg + 1];
|
|
||||||
const bool allow_u_turn_at_via =
|
|
||||||
(use_uturn_default && UTURN_DEFAULT) ||
|
|
||||||
(!use_uturn_default && *uturn_indicators[current_leg + 1]);
|
|
||||||
|
|
||||||
bool search_to_forward_node = target_phantom.forward_node_id != SPECIAL_NODEID;
|
bool search_to_forward_node = target_phantom.forward_node_id != SPECIAL_NODEID;
|
||||||
bool search_to_reverse_node = target_phantom.reverse_node_id != SPECIAL_NODEID;
|
bool search_to_reverse_node = target_phantom.reverse_node_id != SPECIAL_NODEID;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||||
|
|
||||||
#include "extractor/edge_based_edge.hpp"
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "extractor/speed_profile.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/restriction_map.hpp"
|
#include "extractor/restriction_map.hpp"
|
||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
#include "extractor/edge_based_node.hpp"
|
#include "extractor/edge_based_node.hpp"
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "util/deallocating_vector.hpp"
|
||||||
|
#include "util/name_table.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -51,7 +52,8 @@ class EdgeBasedGraphFactory
|
|||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
SpeedProfileProperties speed_profile);
|
ProfileProperties profile_properties,
|
||||||
|
const util::NameTable &name_table);
|
||||||
|
|
||||||
void Run(const std::string &original_edge_data_filename,
|
void Run(const std::string &original_edge_data_filename,
|
||||||
lua_State *lua_state,
|
lua_State *lua_state,
|
||||||
@@ -104,7 +106,9 @@ class EdgeBasedGraphFactory
|
|||||||
const std::unordered_set<NodeID> &m_traffic_lights;
|
const std::unordered_set<NodeID> &m_traffic_lights;
|
||||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||||
|
|
||||||
SpeedProfileProperties speed_profile;
|
ProfileProperties profile_properties;
|
||||||
|
|
||||||
|
const util::NameTable &name_table;
|
||||||
|
|
||||||
void CompressGeometry();
|
void CompressGeometry();
|
||||||
unsigned RenumberEdges();
|
unsigned RenumberEdges();
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct ProfileProperties;
|
||||||
|
|
||||||
class Extractor
|
class Extractor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -49,13 +51,15 @@ class Extractor
|
|||||||
private:
|
private:
|
||||||
ExtractorConfig config;
|
ExtractorConfig config;
|
||||||
|
|
||||||
void SetupScriptingEnvironment(lua_State *myLuaState, SpeedProfileProperties &speed_profile);
|
|
||||||
std::pair<std::size_t, std::size_t>
|
std::pair<std::size_t, std::size_t>
|
||||||
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
|
BuildEdgeExpandedGraph(lua_State* lua_state,
|
||||||
|
const ProfileProperties& profile_properties,
|
||||||
|
std::vector<QueryNode> &internal_to_external_node_map,
|
||||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
||||||
|
void WriteProfileProperties(const std::string& output_path, const ProfileProperties& properties) const;
|
||||||
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
|
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
|
||||||
void FindComponents(unsigned max_edge_id,
|
void FindComponents(unsigned max_edge_id,
|
||||||
const util::DeallocatingVector<EdgeBasedEdge> &edges,
|
const util::DeallocatingVector<EdgeBasedEdge> &edges,
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ struct ExtractorConfig
|
|||||||
edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup";
|
edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup";
|
||||||
edge_penalty_path = basepath + ".osrm.edge_penalties";
|
edge_penalty_path = basepath + ".osrm.edge_penalties";
|
||||||
edge_based_node_weights_output_path = basepath + ".osrm.enw";
|
edge_based_node_weights_output_path = basepath + ".osrm.enw";
|
||||||
|
profile_properties_output_path = basepath + ".osrm.properties";
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::path config_file_path;
|
boost::filesystem::path config_file_path;
|
||||||
@@ -88,6 +89,7 @@ struct ExtractorConfig
|
|||||||
std::string node_output_path;
|
std::string node_output_path;
|
||||||
std::string rtree_nodes_output_path;
|
std::string rtree_nodes_output_path;
|
||||||
std::string rtree_leafs_output_path;
|
std::string rtree_leafs_output_path;
|
||||||
|
std::string profile_properties_output_path;
|
||||||
|
|
||||||
unsigned requested_num_threads;
|
unsigned requested_num_threads;
|
||||||
unsigned small_component_size;
|
unsigned small_component_size;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include "extractor/speed_profile.hpp"
|
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -22,8 +21,6 @@ class GraphCompressor
|
|||||||
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphCompressor(SpeedProfileProperties speed_profile);
|
|
||||||
|
|
||||||
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
RestrictionMap &restriction_map,
|
RestrictionMap &restriction_map,
|
||||||
@@ -34,8 +31,6 @@ class GraphCompressor
|
|||||||
void PrintStatistics(unsigned original_number_of_nodes,
|
void PrintStatistics(unsigned original_number_of_nodes,
|
||||||
unsigned original_number_of_edges,
|
unsigned original_number_of_edges,
|
||||||
const util::NodeBasedDynamicGraph &graph) const;
|
const util::NodeBasedDynamicGraph &graph) const;
|
||||||
|
|
||||||
SpeedProfileProperties speed_profile;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@
|
|||||||
#include "extractor/guidance/classification_data.hpp"
|
#include "extractor/guidance/classification_data.hpp"
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -249,10 +251,11 @@ inline double angularDeviation(const double angle, const double from)
|
|||||||
return std::min(360 - deviation, deviation);
|
return std::min(360 - deviation, deviation);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double getAngularPenalty(const double angle, TurnInstruction instruction)
|
inline double getAngularPenalty(const double angle, DirectionModifier modifier)
|
||||||
{
|
{
|
||||||
|
// these are not aligned with getTurnDirection but represent an ideal center
|
||||||
const double center[] = {0, 45, 90, 135, 180, 225, 270, 315};
|
const double center[] = {0, 45, 90, 135, 180, 225, 270, 315};
|
||||||
return angularDeviation(center[static_cast<int>(instruction.direction_modifier)], angle);
|
return angularDeviation(center[static_cast<int>(modifier)], angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double getTurnConfidence(const double angle, TurnInstruction instruction)
|
inline double getTurnConfidence(const double angle, TurnInstruction instruction)
|
||||||
@@ -262,8 +265,8 @@ inline double getTurnConfidence(const double angle, TurnInstruction instruction)
|
|||||||
if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn)
|
if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn)
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
|
||||||
const double deviations[] = {0, 45, 50, 35, 10, 35, 50, 45};
|
const double deviations[] = {0, 45, 50, 30, 20, 30, 50, 45};
|
||||||
const double difference = getAngularPenalty(angle, instruction);
|
const double difference = getAngularPenalty(angle, instruction.direction_modifier);
|
||||||
const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)];
|
const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)];
|
||||||
return 1.0 - (difference / max_deviation) * (difference / max_deviation);
|
return 1.0 - (difference / max_deviation) * (difference / max_deviation);
|
||||||
}
|
}
|
||||||
@@ -281,7 +284,7 @@ inline DirectionModifier getTurnDirection(const double angle)
|
|||||||
return DirectionModifier::Right;
|
return DirectionModifier::Right;
|
||||||
if (angle >= 140 && angle < 170)
|
if (angle >= 140 && angle < 170)
|
||||||
return DirectionModifier::SlightRight;
|
return DirectionModifier::SlightRight;
|
||||||
if (angle >= 170 && angle <= 190)
|
if (angle >= 165 && angle <= 195)
|
||||||
return DirectionModifier::Straight;
|
return DirectionModifier::Straight;
|
||||||
if (angle > 190 && angle <= 220)
|
if (angle > 190 && angle <= 220)
|
||||||
return DirectionModifier::SlightLeft;
|
return DirectionModifier::SlightLeft;
|
||||||
@@ -295,10 +298,14 @@ inline DirectionModifier getTurnDirection(const double angle)
|
|||||||
// swaps left <-> right modifier types
|
// swaps left <-> right modifier types
|
||||||
inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier)
|
inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier)
|
||||||
{
|
{
|
||||||
const constexpr DirectionModifier results[] = {
|
const constexpr DirectionModifier results[] = {DirectionModifier::UTurn,
|
||||||
DirectionModifier::UTurn, DirectionModifier::SharpLeft, DirectionModifier::Left,
|
DirectionModifier::SharpLeft,
|
||||||
DirectionModifier::SlightLeft, DirectionModifier::Straight, DirectionModifier::SlightRight,
|
DirectionModifier::Left,
|
||||||
DirectionModifier::Right, DirectionModifier::SharpRight};
|
DirectionModifier::SlightLeft,
|
||||||
|
DirectionModifier::Straight,
|
||||||
|
DirectionModifier::SlightRight,
|
||||||
|
DirectionModifier::Right,
|
||||||
|
DirectionModifier::SharpRight};
|
||||||
return results[modifier];
|
return results[modifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,6 +322,81 @@ inline bool isLowPriorityRoadClass(const FunctionalRoadClass road_class)
|
|||||||
road_class == FunctionalRoadClass::SERVICE;
|
road_class == FunctionalRoadClass::SERVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isDistinct(const DirectionModifier first, const DirectionModifier second)
|
||||||
|
{
|
||||||
|
if ((first + 1) % detail::num_direction_modifiers == second)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((second + 1) % detail::num_direction_modifiers == first)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool requiresNameAnnounced(const std::string &from, const std::string &to)
|
||||||
|
{
|
||||||
|
// FIXME, handle in profile to begin with?
|
||||||
|
// this uses the encoding of references in the profile, which is very BAD
|
||||||
|
// Input for this function should be a struct separating streetname, suffix (e.g. road,
|
||||||
|
// boulevard, North, West ...), and a list of references
|
||||||
|
std::string from_name;
|
||||||
|
std::string from_ref;
|
||||||
|
std::string to_name;
|
||||||
|
std::string to_ref;
|
||||||
|
|
||||||
|
// Split from the format "{name} ({ref})" -> name, ref
|
||||||
|
auto split = [](const std::string &name, std::string &out_name, std::string &out_ref)
|
||||||
|
{
|
||||||
|
const auto ref_begin = name.find_first_of('(');
|
||||||
|
if (ref_begin != std::string::npos)
|
||||||
|
{
|
||||||
|
out_name = name.substr(0, ref_begin);
|
||||||
|
out_ref = name.substr(ref_begin + 1, name.find_first_of(')') - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_name = name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
split(from, from_name, from_ref);
|
||||||
|
split(to, to_name, to_ref);
|
||||||
|
|
||||||
|
// check similarity of names
|
||||||
|
auto names_are_empty = from_name.empty() && to_name.empty();
|
||||||
|
auto names_are_equal = from_name == to_name;
|
||||||
|
auto name_is_removed = !from_name.empty() && to_name.empty();
|
||||||
|
// references are contained in one another
|
||||||
|
auto refs_are_empty = from_ref.empty() && to_ref.empty();
|
||||||
|
auto ref_is_contained =
|
||||||
|
!from_ref.empty() && !to_ref.empty() &&
|
||||||
|
(from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos);
|
||||||
|
auto ref_is_removed = !from_ref.empty() && to_ref.empty();
|
||||||
|
|
||||||
|
auto obvious_change = ref_is_contained || names_are_equal ||
|
||||||
|
(names_are_empty && refs_are_empty) || name_is_removed || ref_is_removed;
|
||||||
|
|
||||||
|
return !obvious_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getPriority( const FunctionalRoadClass road_class )
|
||||||
|
{
|
||||||
|
//The road priorities indicate which roads can bee seen as more or less equal.
|
||||||
|
//They are used in Fork-Discovery. Possibly should be moved to profiles post v5?
|
||||||
|
//A fork can happen between road types that are at most 1 priority apart from each other
|
||||||
|
const constexpr int road_priority[] = {10, 0, 10, 2, 10, 4, 10, 6, 10, 8, 10, 11, 10, 12, 10, 14};
|
||||||
|
return road_priority[static_cast<int>(road_class)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool canBeSeenAsFork(const FunctionalRoadClass first, const FunctionalRoadClass second)
|
||||||
|
{
|
||||||
|
// forks require similar road categories
|
||||||
|
// Based on the priorities assigned above, we can set forks only if the road priorities match closely.
|
||||||
|
// Potentially we could include features like number of lanes here and others?
|
||||||
|
// Should also be moved to profiles
|
||||||
|
return std::abs(getPriority(first) - getPriority(second)) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -6,11 +6,14 @@
|
|||||||
#include "extractor/restriction_map.hpp"
|
#include "extractor/restriction_map.hpp"
|
||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
|
|
||||||
|
#include "util/name_table.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -20,42 +23,59 @@ namespace extractor
|
|||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
struct TurnCandidate
|
// What is exposed to the outside
|
||||||
|
struct TurnOperation final
|
||||||
{
|
{
|
||||||
EdgeID eid; // the id of the arc
|
EdgeID eid;
|
||||||
bool valid; // a turn may be relevant to good instructions, even if we cannot take the road
|
double angle;
|
||||||
double angle; // the approximated angle of the turn
|
TurnInstruction instruction;
|
||||||
TurnInstruction instruction; // a proposed instruction
|
};
|
||||||
double confidence; // how close to the border is the turn?
|
|
||||||
|
// For the turn analysis, we require a full list of all connected roads to determine the outcome.
|
||||||
|
// Invalid turns can influence the perceived angles
|
||||||
|
//
|
||||||
|
// aaa(2)aa
|
||||||
|
// a - bbbbb
|
||||||
|
// aaa(1)aa
|
||||||
|
//
|
||||||
|
// will not be perceived as a turn from (1) -> b, and as a U-turn from (1) -> (2).
|
||||||
|
// In addition, they can influence whether a turn is obvious or not.
|
||||||
|
struct ConnectedRoad final
|
||||||
|
{
|
||||||
|
ConnectedRoad(const TurnOperation turn, const bool entry_allowed = false);
|
||||||
|
|
||||||
|
TurnOperation turn;
|
||||||
|
bool entry_allowed; // a turn may be relevant to good instructions, even if we cannot take
|
||||||
|
// the road
|
||||||
|
|
||||||
std::string toString() const
|
std::string toString() const
|
||||||
{
|
{
|
||||||
std::string result = "[turn] ";
|
std::string result = "[connection] ";
|
||||||
result += std::to_string(eid);
|
result += std::to_string(turn.eid);
|
||||||
result += " valid: ";
|
result += " allows entry: ";
|
||||||
result += std::to_string(valid);
|
result += std::to_string(entry_allowed);
|
||||||
result += " angle: ";
|
result += " angle: ";
|
||||||
result += std::to_string(angle);
|
result += std::to_string(turn.angle);
|
||||||
result += " instruction: ";
|
result += " instruction: ";
|
||||||
result += std::to_string(static_cast<std::int32_t>(instruction.type)) + " " +
|
result += std::to_string(static_cast<std::int32_t>(turn.instruction.type)) + " " +
|
||||||
std::to_string(static_cast<std::int32_t>(instruction.direction_modifier));
|
std::to_string(static_cast<std::int32_t>(turn.instruction.direction_modifier));
|
||||||
result += " confidence: ";
|
|
||||||
result += std::to_string(confidence);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TurnAnalysis
|
class TurnAnalysis
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const RestrictionMap &restriction_map,
|
const RestrictionMap &restriction_map,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const CompressedEdgeContainer &compressed_edge_container);
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
|
const util::NameTable &name_table);
|
||||||
|
|
||||||
// the entry into the turn analysis
|
// the entry into the turn analysis
|
||||||
std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||||
@@ -63,12 +83,14 @@ class TurnAnalysis
|
|||||||
const RestrictionMap &restriction_map;
|
const RestrictionMap &restriction_map;
|
||||||
const std::unordered_set<NodeID> &barrier_nodes;
|
const std::unordered_set<NodeID> &barrier_nodes;
|
||||||
const CompressedEdgeContainer &compressed_edge_container;
|
const CompressedEdgeContainer &compressed_edge_container;
|
||||||
|
const util::NameTable &name_table;
|
||||||
|
|
||||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at the
|
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
||||||
|
// the
|
||||||
// node reached
|
// node reached
|
||||||
// from `from_node` via `via_eid`
|
// from `from_node` via `via_eid`
|
||||||
// The resulting candidates have to be analysed for their actual instructions later on.
|
// The resulting candidates have to be analysed for their actual instructions later on.
|
||||||
std::vector<TurnCandidate> getTurnCandidates(const NodeID from_node,
|
std::vector<ConnectedRoad> getConnectedRoads(const NodeID from_node,
|
||||||
const EdgeID via_eid) const;
|
const EdgeID via_eid) const;
|
||||||
|
|
||||||
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
|
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
|
||||||
@@ -82,10 +104,7 @@ class TurnAnalysis
|
|||||||
//
|
//
|
||||||
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
|
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
|
||||||
// 160
|
// 160
|
||||||
std::vector<TurnCandidate>
|
std::vector<ConnectedRoad> mergeSegregatedRoads(std::vector<ConnectedRoad> intersection) const;
|
||||||
mergeSegregatedRoads(const NodeID from_node,
|
|
||||||
const EdgeID via_eid,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// TODO distinguish roundabouts and rotaries
|
// TODO distinguish roundabouts and rotaries
|
||||||
// TODO handle bike/walk cases that allow crossing a roundabout!
|
// TODO handle bike/walk cases that allow crossing a roundabout!
|
||||||
@@ -93,110 +112,86 @@ class TurnAnalysis
|
|||||||
// Processing of roundabouts
|
// Processing of roundabouts
|
||||||
// Produces instructions to enter/exit a roundabout or to stay on it.
|
// Produces instructions to enter/exit a roundabout or to stay on it.
|
||||||
// Performs the distinction between roundabout and rotaries.
|
// Performs the distinction between roundabout and rotaries.
|
||||||
std::vector<TurnCandidate> handleRoundabouts(const NodeID from,
|
std::vector<ConnectedRoad> handleRoundabouts(const EdgeID via_edge,
|
||||||
const EdgeID via_edge,
|
|
||||||
const bool on_roundabout,
|
const bool on_roundabout,
|
||||||
const bool can_enter_roundabout,
|
|
||||||
const bool can_exit_roundabout,
|
const bool can_exit_roundabout,
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
// Indicates a Junction containing a motoryway
|
// Indicates a Junction containing a motoryway
|
||||||
bool isMotorwayJunction(const NodeID from,
|
bool isMotorwayJunction(const EdgeID via_edge,
|
||||||
const EdgeID via_edge,
|
const std::vector<ConnectedRoad> &intersection) const;
|
||||||
const std::vector<TurnCandidate> &turn_candidates) const;
|
|
||||||
|
|
||||||
// Decide whether a turn is a turn or a ramp access
|
// Decide whether a turn is a turn or a ramp access
|
||||||
TurnType findBasicTurnType(const EdgeID via_edge, const TurnCandidate &candidate) const;
|
TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
||||||
|
|
||||||
// Get the Instruction for an obvious turn
|
// Get the Instruction for an obvious turn
|
||||||
// Instruction will be a silent instruction
|
// Instruction will be a silent instruction
|
||||||
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
|
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
const TurnCandidate &candidate) const;
|
const ConnectedRoad &candidate) const;
|
||||||
|
|
||||||
// Helper Function that decides between NoTurn or NewName
|
// Helper Function that decides between NoTurn or NewName
|
||||||
TurnInstruction
|
TurnInstruction
|
||||||
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const TurnCandidate &candidate) const;
|
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
||||||
|
|
||||||
// Basic Turn Handling
|
// Basic Turn Handling
|
||||||
|
|
||||||
// Dead end.
|
// Dead end.
|
||||||
std::vector<TurnCandidate> handleOneWayTurn(const NodeID from,
|
std::vector<ConnectedRoad> handleOneWayTurn(std::vector<ConnectedRoad> intersection) const;
|
||||||
const EdgeID via_edge,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Mode Changes, new names...
|
// Mode Changes, new names...
|
||||||
std::vector<TurnCandidate> handleTwoWayTurn(const NodeID from,
|
std::vector<ConnectedRoad> handleTwoWayTurn(const EdgeID via_edge,
|
||||||
const EdgeID via_edge,
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Forks, T intersections and similar
|
// Forks, T intersections and similar
|
||||||
std::vector<TurnCandidate> handleThreeWayTurn(const NodeID from,
|
std::vector<ConnectedRoad> handleThreeWayTurn(const EdgeID via_edge,
|
||||||
const EdgeID via_edge,
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Normal Intersection. Can still contain forks...
|
// Handling of turns larger then degree three
|
||||||
std::vector<TurnCandidate> handleFourWayTurn(const NodeID from,
|
std::vector<ConnectedRoad> handleComplexTurn(const EdgeID via_edge,
|
||||||
const EdgeID via_edge,
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Fallback for turns of high complexion
|
|
||||||
std::vector<TurnCandidate> handleComplexTurn(const NodeID from,
|
|
||||||
const EdgeID via_edge,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Any Junction containing motorways
|
// Any Junction containing motorways
|
||||||
std::vector<TurnCandidate> handleMotorwayJunction(
|
std::vector<ConnectedRoad> handleMotorwayJunction(
|
||||||
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
|
const EdgeID via_edge, std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
std::vector<TurnCandidate> handleFromMotorway(
|
std::vector<ConnectedRoad> handleFromMotorway(const EdgeID via_edge,
|
||||||
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
std::vector<TurnCandidate> handleMotorwayRamp(
|
std::vector<ConnectedRoad> handleMotorwayRamp(const EdgeID via_edge,
|
||||||
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
||||||
std::vector<TurnCandidate> setTurnTypes(const NodeID from,
|
std::vector<ConnectedRoad> setTurnTypes(const NodeID from,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
// Utility function to handle direction modifier conflicts if reasonably possible
|
|
||||||
std::vector<TurnCandidate> handleConflicts(const NodeID from,
|
|
||||||
const EdgeID via_edge,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// Old fallbacks, to be removed
|
|
||||||
std::vector<TurnCandidate> optimizeRamps(const EdgeID via_edge,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
std::vector<TurnCandidate> optimizeCandidates(const EdgeID via_eid,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
bool isObviousChoice(const EdgeID via_eid,
|
|
||||||
const std::size_t turn_index,
|
|
||||||
const std::vector<TurnCandidate> &turn_candidates) const;
|
|
||||||
|
|
||||||
std::vector<TurnCandidate> suppressTurns(const EdgeID via_eid,
|
|
||||||
std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
|
||||||
// node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
|
|
||||||
TurnInstruction AnalyzeTurn(const NodeID node_u,
|
|
||||||
const EdgeID edge1,
|
|
||||||
const NodeID node_v,
|
|
||||||
const EdgeID edge2,
|
|
||||||
const NodeID node_w,
|
|
||||||
const double angle) const;
|
|
||||||
|
|
||||||
// Assignment of specific turn types
|
// Assignment of specific turn types
|
||||||
void assignFork(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
|
void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
||||||
void assignFork(const EdgeID via_edge,
|
void assignFork(const EdgeID via_edge,
|
||||||
TurnCandidate &left,
|
ConnectedRoad &left,
|
||||||
TurnCandidate ¢er,
|
ConnectedRoad ¢er,
|
||||||
TurnCandidate &right) const;
|
ConnectedRoad &right) const;
|
||||||
|
|
||||||
//Type specific fallbacks
|
void
|
||||||
std::vector<TurnCandidate>
|
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
||||||
fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) const;
|
|
||||||
|
// Type specific fallbacks
|
||||||
|
std::vector<ConnectedRoad>
|
||||||
|
fallbackTurnAssignmentMotorway(std::vector<ConnectedRoad> intersection) const;
|
||||||
|
|
||||||
|
// Classification
|
||||||
|
std::size_t findObviousTurn(const EdgeID via_edge,
|
||||||
|
const std::vector<ConnectedRoad> &intersection) const;
|
||||||
|
std::pair<std::size_t, std::size_t>
|
||||||
|
findFork(const std::vector<ConnectedRoad> &intersection) const;
|
||||||
|
|
||||||
|
std::vector<ConnectedRoad> assignLeftTurns(const EdgeID via_edge,
|
||||||
|
std::vector<ConnectedRoad> intersection,
|
||||||
|
const std::size_t starting_at) const;
|
||||||
|
std::vector<ConnectedRoad> assignRightTurns(const EdgeID via_edge,
|
||||||
|
std::vector<ConnectedRoad> intersection,
|
||||||
|
const std::size_t up_to) const;
|
||||||
|
|
||||||
}; // class TurnAnalysis
|
}; // class TurnAnalysis
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,16 @@ enum TurnType // at the moment we can support 32 turn types, without increasing
|
|||||||
NewName, // no turn, but name changes
|
NewName, // no turn, but name changes
|
||||||
Continue, // remain on a street
|
Continue, // remain on a street
|
||||||
Turn, // basic turn
|
Turn, // basic turn
|
||||||
|
FirstTurn, // First of x turns
|
||||||
|
SecondTurn, // Second of x turns
|
||||||
|
ThirdTurn, // Third of x turns
|
||||||
|
FourthTurn, // Fourth of x turns
|
||||||
Merge, // merge onto a street
|
Merge, // merge onto a street
|
||||||
Ramp, // special turn (highway ramp exits)
|
Ramp, // special turn (highway ramp exits)
|
||||||
|
FirstRamp, // first turn onto a ramp
|
||||||
|
SecondRamp, // second turn onto a ramp
|
||||||
|
ThirdRamp, // third turn onto a ramp
|
||||||
|
FourthRamp, // fourth turn onto a ramp
|
||||||
Fork, // fork road splitting up
|
Fork, // fork road splitting up
|
||||||
EndOfRoad, // T intersection
|
EndOfRoad, // T intersection
|
||||||
EnterRoundabout, // Entering a small Roundabout
|
EnterRoundabout, // Entering a small Roundabout
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef PROFILE_PROPERTIES_HPP
|
||||||
|
#define PROFILE_PROPERTIES_HPP
|
||||||
|
|
||||||
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ProfileProperties
|
||||||
|
{
|
||||||
|
ProfileProperties()
|
||||||
|
: traffic_signal_penalty(0), u_turn_penalty(0), allow_u_turn_at_via(false), use_turn_restrictions(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetUturnPenalty() const
|
||||||
|
{
|
||||||
|
return u_turn_penalty / 10.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUturnPenalty(const double u_turn_penalty_)
|
||||||
|
{
|
||||||
|
u_turn_penalty = boost::numeric_cast<int>(u_turn_penalty_ * 10.);
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetTrafficSignalPenalty() const
|
||||||
|
{
|
||||||
|
return traffic_signal_penalty / 10.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTrafficSignalPenalty(const double traffic_signal_penalty_)
|
||||||
|
{
|
||||||
|
traffic_signal_penalty = boost::numeric_cast<int>(traffic_signal_penalty_ * 10.);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! penalty to cross a traffic light in deci-seconds
|
||||||
|
int traffic_signal_penalty;
|
||||||
|
//! penalty to do a uturn in deci-seconds
|
||||||
|
int u_turn_penalty;
|
||||||
|
bool allow_u_turn_at_via;
|
||||||
|
bool use_turn_restrictions;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,6 +19,8 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class ProfileProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the relations that represents turn restrictions.
|
* Parses the relations that represents turn restrictions.
|
||||||
*
|
*
|
||||||
@@ -40,11 +42,10 @@ namespace extractor
|
|||||||
class RestrictionParser
|
class RestrictionParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RestrictionParser(lua_State *lua_state);
|
RestrictionParser(lua_State *lua_state, const ProfileProperties& properties);
|
||||||
boost::optional<InputRestrictionContainer> TryParse(const osmium::Relation &relation) const;
|
boost::optional<InputRestrictionContainer> TryParse(const osmium::Relation &relation) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadUseRestrictionsSetting(lua_State *lua_state);
|
|
||||||
void ReadRestrictionExceptions(lua_State *lua_state);
|
void ReadRestrictionExceptions(lua_State *lua_state);
|
||||||
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#ifndef SCRIPTING_ENVIRONMENT_HPP
|
#ifndef SCRIPTING_ENVIRONMENT_HPP
|
||||||
#define SCRIPTING_ENVIRONMENT_HPP
|
#define SCRIPTING_ENVIRONMENT_HPP
|
||||||
|
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
|
#include "extractor/raster_source.hpp"
|
||||||
|
|
||||||
|
#include "util/lua_util.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -23,18 +28,25 @@ namespace extractor
|
|||||||
class ScriptingEnvironment
|
class ScriptingEnvironment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Context
|
||||||
|
{
|
||||||
|
ProfileProperties properties;
|
||||||
|
SourceContainer sources;
|
||||||
|
util::LuaState state;
|
||||||
|
};
|
||||||
|
|
||||||
explicit ScriptingEnvironment(const std::string &file_name);
|
explicit ScriptingEnvironment(const std::string &file_name);
|
||||||
|
|
||||||
ScriptingEnvironment(const ScriptingEnvironment &) = delete;
|
ScriptingEnvironment(const ScriptingEnvironment &) = delete;
|
||||||
ScriptingEnvironment &operator=(const ScriptingEnvironment &) = delete;
|
ScriptingEnvironment &operator=(const ScriptingEnvironment &) = delete;
|
||||||
|
|
||||||
lua_State *GetLuaState();
|
Context &GetContex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitLuaState(lua_State *lua_state);
|
void InitContext(Context &context);
|
||||||
std::mutex init_mutex;
|
std::mutex init_mutex;
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
|
tbb::enumerable_thread_specific<std::unique_ptr<Context>> script_contexts;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#ifndef SPEED_PROFILE_PROPERTIES_HPP
|
|
||||||
#define SPEED_PROFILE_PROPERTIES_HPP
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
struct SpeedProfileProperties
|
|
||||||
{
|
|
||||||
SpeedProfileProperties()
|
|
||||||
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int traffic_signal_penalty;
|
|
||||||
int u_turn_penalty;
|
|
||||||
bool has_turn_penalty_function;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2016, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLOBAL_STORAGE_CONFIG_HPP
|
||||||
|
#define GLOBAL_STORAGE_CONFIG_HPP
|
||||||
|
|
||||||
|
#include "storage/storage_config.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
using storage::StorageConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -27,7 +27,7 @@ struct RouteParametersGrammar : public BaseParametersGrammar
|
|||||||
using AlternativeT = bool;
|
using AlternativeT = bool;
|
||||||
using GeometriesT = engine::api::RouteParameters::GeometriesType;
|
using GeometriesT = engine::api::RouteParameters::GeometriesType;
|
||||||
using OverviewT = engine::api::RouteParameters::OverviewType;
|
using OverviewT = engine::api::RouteParameters::OverviewType;
|
||||||
using UturnsT = std::vector<boost::optional<bool>>;
|
using UturnsT = bool;
|
||||||
|
|
||||||
RouteParametersGrammar() : BaseParametersGrammar(root_rule, parameters)
|
RouteParametersGrammar() : BaseParametersGrammar(root_rule, parameters)
|
||||||
{
|
{
|
||||||
@@ -72,9 +72,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar
|
|||||||
overview_rule = qi::lit("overview=simplified")[set_simplified_type] |
|
overview_rule = qi::lit("overview=simplified")[set_simplified_type] |
|
||||||
qi::lit("overview=full")[set_full_type] |
|
qi::lit("overview=full")[set_full_type] |
|
||||||
qi::lit("overview=false")[set_false_type];
|
qi::lit("overview=false")[set_false_type];
|
||||||
uturns_rule = qi::lit("uturns=") >> -qi::bool_ % ";";
|
uturns_rule = qi::lit("uturns=default") | (qi::lit("uturns=") >> qi::bool_)[set_uturns];
|
||||||
route_rule = steps_rule[set_steps] | alternatives_rule[set_alternatives] | geometries_rule |
|
route_rule = steps_rule[set_steps] | alternatives_rule[set_alternatives] | geometries_rule |
|
||||||
overview_rule | uturns_rule[set_uturns];
|
overview_rule | uturns_rule;
|
||||||
|
|
||||||
root_rule =
|
root_rule =
|
||||||
query_rule >> -qi::lit(".json") >> -(qi::lit("?") >> (route_rule | base_rule) % '&');
|
query_rule >> -qi::lit(".json") >> -(qi::lit("?") >> (route_rule | base_rule) % '&');
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ class Server
|
|||||||
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||||
acceptor.bind(endpoint);
|
acceptor.bind(endpoint);
|
||||||
acceptor.listen();
|
acceptor.listen();
|
||||||
|
|
||||||
|
util::SimpleLogger().Write() << "Listening on: " << acceptor.local_endpoint();
|
||||||
|
|
||||||
acceptor.async_accept(
|
acceptor.async_accept(
|
||||||
new_connection->socket(),
|
new_connection->socket(),
|
||||||
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
|
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ struct SharedDataLayout
|
|||||||
DATASOURCE_NAME_DATA,
|
DATASOURCE_NAME_DATA,
|
||||||
DATASOURCE_NAME_OFFSETS,
|
DATASOURCE_NAME_OFFSETS,
|
||||||
DATASOURCE_NAME_LENGTHS,
|
DATASOURCE_NAME_LENGTHS,
|
||||||
|
PROPERTIES,
|
||||||
NUM_BLOCKS
|
NUM_BLOCKS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
#ifndef STORAGE_HPP
|
#ifndef STORAGE_HPP
|
||||||
#define STORAGE_HPP
|
#define STORAGE_HPP
|
||||||
|
|
||||||
|
#include "storage/storage_config.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace storage
|
namespace storage
|
||||||
{
|
{
|
||||||
using DataPaths = std::unordered_map<std::string, boost::filesystem::path>;
|
|
||||||
class Storage
|
class Storage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Storage(const DataPaths &data_paths);
|
Storage(StorageConfig config);
|
||||||
int Run();
|
int Run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataPaths paths;
|
StorageConfig config;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef STORAGE_CONFIG_HPP
|
||||||
|
#define STORAGE_CONFIG_HPP
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace storage
|
||||||
|
{
|
||||||
|
struct StorageConfig
|
||||||
|
{
|
||||||
|
StorageConfig() = default;
|
||||||
|
StorageConfig(const boost::filesystem::path &base);
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
boost::filesystem::path ram_index_path;
|
||||||
|
boost::filesystem::path file_index_path;
|
||||||
|
boost::filesystem::path hsgr_data_path;
|
||||||
|
boost::filesystem::path nodes_data_path;
|
||||||
|
boost::filesystem::path edges_data_path;
|
||||||
|
boost::filesystem::path core_data_path;
|
||||||
|
boost::filesystem::path geometries_path;
|
||||||
|
boost::filesystem::path timestamp_path;
|
||||||
|
boost::filesystem::path datasource_names_path;
|
||||||
|
boost::filesystem::path datasource_indexes_path;
|
||||||
|
boost::filesystem::path names_data_path;
|
||||||
|
boost::filesystem::path properties_path;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,20 +3,34 @@
|
|||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
|
|
||||||
|
#include <boost/math/constants/constants.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
namespace coordinate_calculation
|
||||||
|
{
|
||||||
|
|
||||||
const constexpr long double RAD = 0.017453292519943295769236907684886;
|
const constexpr long double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
|
||||||
|
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
|
||||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||||
const constexpr long double EARTH_RADIUS = 6372797.560856;
|
const constexpr long double EARTH_RADIUS = 6372797.560856;
|
||||||
|
// radius used by WGS84
|
||||||
|
const constexpr double EARTH_RADIUS_WGS84 = 6378137.0;
|
||||||
|
|
||||||
namespace coordinate_calculation
|
namespace detail
|
||||||
{
|
{
|
||||||
|
// earth circumference devided by 2
|
||||||
|
const constexpr double MAXEXTENT = EARTH_RADIUS_WGS84 * boost::math::constants::pi<double>();
|
||||||
|
// ^ math functions are not constexpr since they have side-effects (setting errno) :(
|
||||||
|
const double MAX_LATITUDE = RAD_TO_DEGREE * (2.0 * std::atan(std::exp(180.0 * DEGREE_TO_RAD)) - boost::math::constants::half_pi<double>());
|
||||||
|
const constexpr double MAX_LONGITUDE = 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Projects both coordinates and takes the euclidean distance of the projected points
|
//! Projects both coordinates and takes the euclidean distance of the projected points
|
||||||
// Does not return meters!
|
// Does not return meters!
|
||||||
@@ -50,9 +64,6 @@ double perpendicularDistanceFromProjectedCoordinate(
|
|||||||
Coordinate &nearest_location,
|
Coordinate &nearest_location,
|
||||||
double &ratio);
|
double &ratio);
|
||||||
|
|
||||||
double degToRad(const double degree);
|
|
||||||
double radToDeg(const double radian);
|
|
||||||
|
|
||||||
double bearing(const Coordinate first_coordinate, const Coordinate second_coordinate);
|
double bearing(const Coordinate first_coordinate, const Coordinate second_coordinate);
|
||||||
|
|
||||||
// Get angle of line segment (A,C)->(C,B)
|
// Get angle of line segment (A,C)->(C,B)
|
||||||
@@ -64,8 +75,17 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
|
|||||||
|
|
||||||
namespace mercator
|
namespace mercator
|
||||||
{
|
{
|
||||||
|
// This is the global default tile size for all Mapbox Vector Tiles
|
||||||
|
const constexpr double TILE_SIZE = 256.0;
|
||||||
|
// Converts projected mercator degrees to PX
|
||||||
|
const constexpr double DEGREE_TO_PX = detail::MAXEXTENT / 180.0;
|
||||||
|
|
||||||
|
double degreeToPixel(FloatLatitude lat, unsigned zoom);
|
||||||
|
double degreeToPixel(FloatLongitude lon, unsigned zoom);
|
||||||
FloatLatitude yToLat(const double value);
|
FloatLatitude yToLat(const double value);
|
||||||
double latToY(const FloatLatitude latitude);
|
double latToY(const FloatLatitude latitude);
|
||||||
|
void xyzToMercator(const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy);
|
||||||
|
void xyzToWSG84(const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy);
|
||||||
} // ns mercator
|
} // ns mercator
|
||||||
} // ns coordinate_calculation
|
} // ns coordinate_calculation
|
||||||
} // ns util
|
} // ns util
|
||||||
|
|||||||
@@ -18,10 +18,19 @@ namespace osrm
|
|||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename T> void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; }
|
struct LuaState
|
||||||
|
{
|
||||||
|
LuaState() : handle{::luaL_newstate(), &::lua_close} { luaL_openlibs(*this); }
|
||||||
|
|
||||||
|
operator lua_State *() { return handle.get(); }
|
||||||
|
operator lua_State const *() const { return handle.get(); }
|
||||||
|
|
||||||
|
using handle_type = std::unique_ptr<lua_State, decltype(&::lua_close)>;
|
||||||
|
handle_type handle;
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the lua function <name> is defined
|
// Check if the lua function <name> is defined
|
||||||
inline bool lua_function_exists(lua_State *lua_state, const char *name)
|
inline bool luaFunctionExists(lua_State *lua_state, const char *name)
|
||||||
{
|
{
|
||||||
luabind::object globals_table = luabind::globals(lua_state);
|
luabind::object globals_table = luabind::globals(lua_state);
|
||||||
luabind::object lua_function = globals_table[name];
|
luabind::object lua_function = globals_table[name];
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef OSRM_UTIL_NAME_TABLE_HPP
|
||||||
|
#define OSRM_UTIL_NAME_TABLE_HPP
|
||||||
|
|
||||||
|
#include "util/shared_memory_vector_wrapper.hpp"
|
||||||
|
#include "util/range_table.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
|
||||||
|
// While this could, theoretically, hold any names in the fitting format,
|
||||||
|
// the NameTable allows access to a part of the Datafacade to allow
|
||||||
|
// processing based on name indices.
|
||||||
|
class NameTable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// FIXME should this use shared memory
|
||||||
|
RangeTable<16, false> m_name_table;
|
||||||
|
ShM<char, false>::vector m_names_char_list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NameTable(const std::string &filename);
|
||||||
|
std::string GetNameForID(const unsigned name_id) const;
|
||||||
|
};
|
||||||
|
} // namespace util
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // OSRM_UTIL_NAME_TABLE_HPP
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
#ifndef ROUTED_OPTIONS_HPP
|
|
||||||
#define ROUTED_OPTIONS_HPP
|
|
||||||
|
|
||||||
#include "util/version.hpp"
|
|
||||||
#include "util/exception.hpp"
|
|
||||||
#include "util/simple_logger.hpp"
|
|
||||||
|
|
||||||
#include <boost/any.hpp>
|
|
||||||
#include <boost/program_options.hpp>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
|
||||||
#include <boost/filesystem/operations.hpp>
|
|
||||||
#include <boost/filesystem/convenience.hpp>
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
const static unsigned INIT_OK_START_ENGINE = 0;
|
|
||||||
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
|
|
||||||
const static unsigned INIT_FAILED = -1;
|
|
||||||
|
|
||||||
inline void
|
|
||||||
populate_base_path(std::unordered_map<std::string, boost::filesystem::path> &server_paths)
|
|
||||||
{
|
|
||||||
// populate the server_path object
|
|
||||||
auto path_iterator = server_paths.find("base");
|
|
||||||
|
|
||||||
// if a base path has been set, we populate it.
|
|
||||||
if (path_iterator != server_paths.end())
|
|
||||||
{
|
|
||||||
const std::string base_string = path_iterator->second.string();
|
|
||||||
SimpleLogger().Write() << "populating base path: " << base_string;
|
|
||||||
|
|
||||||
server_paths["hsgrdata"] = base_string + ".hsgr";
|
|
||||||
BOOST_ASSERT(server_paths.find("hsgrdata") != server_paths.end());
|
|
||||||
server_paths["nodesdata"] = base_string + ".nodes";
|
|
||||||
BOOST_ASSERT(server_paths.find("nodesdata") != server_paths.end());
|
|
||||||
server_paths["coredata"] = base_string + ".core";
|
|
||||||
BOOST_ASSERT(server_paths.find("coredata") != server_paths.end());
|
|
||||||
server_paths["edgesdata"] = base_string + ".edges";
|
|
||||||
BOOST_ASSERT(server_paths.find("edgesdata") != server_paths.end());
|
|
||||||
server_paths["geometries"] = base_string + ".geometry";
|
|
||||||
BOOST_ASSERT(server_paths.find("geometries") != server_paths.end());
|
|
||||||
server_paths["ramindex"] = base_string + ".ramIndex";
|
|
||||||
BOOST_ASSERT(server_paths.find("ramindex") != server_paths.end());
|
|
||||||
server_paths["fileindex"] = base_string + ".fileIndex";
|
|
||||||
BOOST_ASSERT(server_paths.find("fileindex") != server_paths.end());
|
|
||||||
server_paths["namesdata"] = base_string + ".names";
|
|
||||||
BOOST_ASSERT(server_paths.find("namesdata") != server_paths.end());
|
|
||||||
server_paths["timestamp"] = base_string + ".timestamp";
|
|
||||||
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
|
|
||||||
server_paths["datasource_indexes"] = base_string + ".datasource_indexes";
|
|
||||||
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
|
|
||||||
server_paths["datasource_names"] = base_string + ".datasource_names";
|
|
||||||
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if files are give and whether they exist at all
|
|
||||||
path_iterator = server_paths.find("hsgrdata");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".hsgr not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("nodesdata");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".nodes not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("edgesdata");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".edges not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("geometries");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".geometry not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("ramindex");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".ramIndex not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("fileindex");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".fileIndex not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = server_paths.find("namesdata");
|
|
||||||
if (path_iterator == server_paths.end() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw exception(".namesIndex not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"];
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate boost::program_options object for the routing part
|
|
||||||
inline unsigned
|
|
||||||
GenerateServerProgramOptions(const int argc,
|
|
||||||
const char *argv[],
|
|
||||||
std::unordered_map<std::string, boost::filesystem::path> &paths,
|
|
||||||
std::string &ip_address,
|
|
||||||
int &ip_port,
|
|
||||||
int &requested_num_threads,
|
|
||||||
bool &use_shared_memory,
|
|
||||||
bool &trial,
|
|
||||||
int &max_locations_trip,
|
|
||||||
int &max_locations_viaroute,
|
|
||||||
int &max_locations_distance_table,
|
|
||||||
int &max_locations_map_matching)
|
|
||||||
{
|
|
||||||
using boost::program_options::value;
|
|
||||||
using boost::filesystem::path;
|
|
||||||
|
|
||||||
// declare a group of options that will be allowed only on command line
|
|
||||||
boost::program_options::options_description generic_options("Options");
|
|
||||||
generic_options.add_options() //
|
|
||||||
("version,v", "Show version")("help,h", "Show this help message") //
|
|
||||||
("config,c", value<boost::filesystem::path>(&paths["config"])->default_value("server.ini"),
|
|
||||||
"Path to a configuration file") //
|
|
||||||
("trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
|
|
||||||
|
|
||||||
// declare a group of options that will be allowed on command line
|
|
||||||
boost::program_options::options_description config_options("Configuration");
|
|
||||||
config_options.add_options() //
|
|
||||||
("hsgrdata", value<boost::filesystem::path>(&paths["hsgrdata"]), ".hsgr file") //
|
|
||||||
("nodesdata", value<boost::filesystem::path>(&paths["nodesdata"]), ".nodes file") //
|
|
||||||
("edgesdata", value<boost::filesystem::path>(&paths["edgesdata"]), ".edges file") //
|
|
||||||
("geometry", value<boost::filesystem::path>(&paths["geometries"]), ".geometry file") //
|
|
||||||
("ramindex", value<boost::filesystem::path>(&paths["ramindex"]), ".ramIndex file") //
|
|
||||||
("fileindex", value<boost::filesystem::path>(&paths["fileindex"]),
|
|
||||||
"File index file") //
|
|
||||||
("namesdata", value<boost::filesystem::path>(&paths["namesdata"]),
|
|
||||||
".names file") //
|
|
||||||
("timestamp", value<boost::filesystem::path>(&paths["timestamp"]),
|
|
||||||
".timestamp file") //
|
|
||||||
("ip,i", value<std::string>(&ip_address)->default_value("0.0.0.0"),
|
|
||||||
"IP address") //
|
|
||||||
("port,p", value<int>(&ip_port)->default_value(5000),
|
|
||||||
"TCP/IP port") //
|
|
||||||
("threads,t", value<int>(&requested_num_threads)->default_value(8),
|
|
||||||
"Number of threads to use") //
|
|
||||||
("shared-memory,s",
|
|
||||||
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false),
|
|
||||||
"Load data from shared memory") //
|
|
||||||
("max-viaroute-size", value<int>(&max_locations_viaroute)->default_value(500),
|
|
||||||
"Max. locations supported in viaroute query") //
|
|
||||||
("max-trip-size", value<int>(&max_locations_trip)->default_value(100),
|
|
||||||
"Max. locations supported in trip query") //
|
|
||||||
("max-table-size", value<int>(&max_locations_distance_table)->default_value(100),
|
|
||||||
"Max. locations supported in distance table query") //
|
|
||||||
("max-matching-size", value<int>(&max_locations_map_matching)->default_value(100),
|
|
||||||
"Max. locations supported in map matching query");
|
|
||||||
|
|
||||||
// hidden options, will be allowed on command line, but will not be shown to the user
|
|
||||||
boost::program_options::options_description hidden_options("Hidden options");
|
|
||||||
hidden_options.add_options()("base,b", value<boost::filesystem::path>(&paths["base"]),
|
|
||||||
"base path to .osrm file");
|
|
||||||
|
|
||||||
// positional option
|
|
||||||
boost::program_options::positional_options_description positional_options;
|
|
||||||
positional_options.add("base", 1);
|
|
||||||
|
|
||||||
// combine above options for parsing
|
|
||||||
boost::program_options::options_description cmdline_options;
|
|
||||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
|
||||||
|
|
||||||
boost::program_options::options_description visible_options(
|
|
||||||
boost::filesystem::basename(argv[0]) + " <base.osrm> [<options>]");
|
|
||||||
visible_options.add(generic_options).add(config_options);
|
|
||||||
|
|
||||||
// parse command line options
|
|
||||||
boost::program_options::variables_map option_variables;
|
|
||||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
|
||||||
.options(cmdline_options)
|
|
||||||
.positional(positional_options)
|
|
||||||
.run(),
|
|
||||||
option_variables);
|
|
||||||
|
|
||||||
if (option_variables.count("version"))
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << OSRM_VERSION;
|
|
||||||
return INIT_OK_DO_NOT_START_ENGINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option_variables.count("help"))
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << visible_options;
|
|
||||||
return INIT_OK_DO_NOT_START_ENGINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::program_options::notify(option_variables);
|
|
||||||
|
|
||||||
if (1 > requested_num_threads)
|
|
||||||
{
|
|
||||||
throw exception("Number of threads must be a positive number");
|
|
||||||
}
|
|
||||||
if (2 > max_locations_distance_table)
|
|
||||||
{
|
|
||||||
throw exception("Max location for distance table must be at least two");
|
|
||||||
}
|
|
||||||
if (max_locations_map_matching > 0 && 2 > max_locations_map_matching)
|
|
||||||
{
|
|
||||||
throw exception("Max location for map matching must be at least two");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!use_shared_memory && option_variables.count("base"))
|
|
||||||
{
|
|
||||||
return INIT_OK_START_ENGINE;
|
|
||||||
}
|
|
||||||
else if (use_shared_memory && !option_variables.count("base"))
|
|
||||||
{
|
|
||||||
return INIT_OK_START_ENGINE;
|
|
||||||
}
|
|
||||||
else if (use_shared_memory && option_variables.count("base"))
|
|
||||||
{
|
|
||||||
SimpleLogger().Write(logWARNING) << "Shared memory settings conflict with path settings.";
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() << visible_options;
|
|
||||||
return INIT_OK_DO_NOT_START_ENGINE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ROUTED_OPTIONS_HPP
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#ifndef UTIL_TILES_HPP
|
|
||||||
#define UTIL_TILES_HPP
|
|
||||||
|
|
||||||
#include "util/coordinate.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
// This is a port of the tilebelt algorithm https://github.com/mapbox/tilebelt
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
namespace tiles
|
|
||||||
{
|
|
||||||
struct Tile
|
|
||||||
{
|
|
||||||
unsigned x;
|
|
||||||
unsigned y;
|
|
||||||
unsigned z;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
// optimized for 32bit integers
|
|
||||||
static constexpr unsigned MAX_ZOOM = 32;
|
|
||||||
|
|
||||||
// Returns 1-indexed 1..32 of MSB if value > 0 or 0 if value == 0
|
|
||||||
inline unsigned getMSBPosition(std::uint32_t value)
|
|
||||||
{
|
|
||||||
if (value == 0)
|
|
||||||
return 0;
|
|
||||||
std::uint8_t pos = 1;
|
|
||||||
while (value >>= 1)
|
|
||||||
pos++;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned getBBMaxZoom(const Tile top_left, const Tile bottom_left)
|
|
||||||
{
|
|
||||||
auto x_xor = top_left.x ^ bottom_left.x;
|
|
||||||
auto y_xor = top_left.y ^ bottom_left.y;
|
|
||||||
auto lon_msb = detail::getMSBPosition(x_xor);
|
|
||||||
auto lat_msb = detail::getMSBPosition(y_xor);
|
|
||||||
return MAX_ZOOM - std::max(lon_msb, lat_msb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Tile pointToTile(const FloatLongitude lon, const FloatLatitude lat)
|
|
||||||
{
|
|
||||||
auto sin_lat = std::sin(static_cast<double>(lat) * M_PI / 180.);
|
|
||||||
auto p2z = std::pow(2, detail::MAX_ZOOM);
|
|
||||||
unsigned x = p2z * (static_cast<double>(lon) / 360. + 0.5);
|
|
||||||
unsigned y = p2z * (0.5 - 0.25 * std::log((1 + sin_lat) / (1 - sin_lat)) / M_PI);
|
|
||||||
|
|
||||||
return Tile{x, y, detail::MAX_ZOOM};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Tile getBBMaxZoomTile(const FloatLongitude min_lon,
|
|
||||||
const FloatLatitude min_lat,
|
|
||||||
const FloatLongitude max_lon,
|
|
||||||
const FloatLatitude max_lat)
|
|
||||||
{
|
|
||||||
const auto top_left = pointToTile(min_lon, min_lat);
|
|
||||||
const auto bottom_left = pointToTile(max_lon, max_lat);
|
|
||||||
BOOST_ASSERT(top_left.z == detail::MAX_ZOOM);
|
|
||||||
BOOST_ASSERT(bottom_left.z == detail::MAX_ZOOM);
|
|
||||||
|
|
||||||
const auto max_zoom = detail::getBBMaxZoom(top_left, bottom_left);
|
|
||||||
|
|
||||||
if (max_zoom == 0)
|
|
||||||
{
|
|
||||||
return Tile{0, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto x = top_left.x >> (detail::MAX_ZOOM - max_zoom);
|
|
||||||
auto y = top_left.y >> (detail::MAX_ZOOM - max_zoom);
|
|
||||||
|
|
||||||
return Tile{x, y, max_zoom};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef UTIL_VIEWPORT_HPP
|
||||||
|
#define UTIL_VIEWPORT_HPP
|
||||||
|
|
||||||
|
#include "util/coordinate.hpp"
|
||||||
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
// Port of https://github.com/mapbox/geo-viewport
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
namespace viewport
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
static constexpr unsigned MAX_ZOOM = 18;
|
||||||
|
static constexpr unsigned MIN_ZOOM = 1;
|
||||||
|
// this is an upper bound to current display sizes
|
||||||
|
static constexpr double VIEWPORT_WIDTH = 8 * coordinate_calculation::mercator::TILE_SIZE;
|
||||||
|
static constexpr double VIEWPORT_HEIGHT = 5 * coordinate_calculation::mercator::TILE_SIZE;
|
||||||
|
static double INV_LOG_2 = 1. / std::log(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getFittedZoom(util::Coordinate south_west, util::Coordinate north_east)
|
||||||
|
{
|
||||||
|
const auto min_x = coordinate_calculation::mercator::degreeToPixel(toFloating(south_west.lon), detail::MAX_ZOOM);
|
||||||
|
const auto max_y = coordinate_calculation::mercator::degreeToPixel(toFloating(south_west.lat), detail::MAX_ZOOM);
|
||||||
|
const auto max_x = coordinate_calculation::mercator::degreeToPixel(toFloating(north_east.lon), detail::MAX_ZOOM);
|
||||||
|
const auto min_y = coordinate_calculation::mercator::degreeToPixel(toFloating(north_east.lat), detail::MAX_ZOOM);
|
||||||
|
const double width_ratio = (max_x - min_x) / detail::VIEWPORT_WIDTH;
|
||||||
|
const double height_ratio = (max_y - min_y) / detail::VIEWPORT_HEIGHT;
|
||||||
|
const auto zoom = detail::MAX_ZOOM - std::max(std::log(width_ratio), std::log(height_ratio)) * detail::INV_LOG_2;
|
||||||
|
|
||||||
|
return std::max<unsigned>(detail::MIN_ZOOM, zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -91,9 +91,10 @@ surface_speeds = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- these need to be global because they are accesed externaly
|
-- these need to be global because they are accesed externaly
|
||||||
traffic_signal_penalty = 2
|
properties.traffic_signal_penalty = 2
|
||||||
use_turn_restrictions = false
|
properties.use_turn_restrictions = false
|
||||||
u_turn_penalty = 20
|
properties.u_turn_penalty = 20
|
||||||
|
properties.allow_u_turn_at_via = true
|
||||||
|
|
||||||
local obey_oneway = true
|
local obey_oneway = true
|
||||||
local ignore_areas = true
|
local ignore_areas = true
|
||||||
|
|||||||
+9
-9
@@ -128,20 +128,20 @@ maxspeed_table = {
|
|||||||
["uk:motorway"] = (70*1609)/1000
|
["uk:motorway"] = (70*1609)/1000
|
||||||
}
|
}
|
||||||
|
|
||||||
-- these need to be global because they are accesed externaly
|
-- set profile properties
|
||||||
u_turn_penalty = 20
|
properties.u_turn_penalty = 20
|
||||||
traffic_signal_penalty = 2
|
properties.traffic_signal_penalty = 2
|
||||||
use_turn_restrictions = true
|
properties.use_turn_restrictions = true
|
||||||
|
|
||||||
side_road_speed_multiplier = 0.8
|
local side_road_speed_multiplier = 0.8
|
||||||
|
|
||||||
local turn_penalty = 10
|
local turn_penalty = 10
|
||||||
-- Note: this biases right-side driving. Should be
|
-- Note: this biases right-side driving. Should be
|
||||||
-- inverted for left-driving countries.
|
-- inverted for left-driving countries.
|
||||||
local turn_bias = 1.2
|
local turn_bias = 1.2
|
||||||
|
|
||||||
local obey_oneway = true
|
local obey_oneway = true
|
||||||
local ignore_areas = true
|
local ignore_areas = true
|
||||||
|
|
||||||
local abs = math.abs
|
local abs = math.abs
|
||||||
local min = math.min
|
local min = math.min
|
||||||
|
|||||||
+5
-3
@@ -64,9 +64,11 @@ leisure_speeds = {
|
|||||||
["track"] = walking_speed
|
["track"] = walking_speed
|
||||||
}
|
}
|
||||||
|
|
||||||
traffic_signal_penalty = 2
|
properties.traffic_signal_penalty = 2
|
||||||
u_turn_penalty = 2
|
properties.u_turn_penalty = 2
|
||||||
use_turn_restrictions = false
|
properties.use_turn_restrictions = false
|
||||||
|
properties.allow_u_turn_at_via = true
|
||||||
|
|
||||||
local fallback_names = true
|
local fallback_names = true
|
||||||
|
|
||||||
function get_exceptions(vector)
|
function get_exceptions(vector)
|
||||||
|
|||||||
@@ -32,15 +32,15 @@ end
|
|||||||
function segment_function (source, target, distance, weight)
|
function segment_function (source, target, distance, weight)
|
||||||
local sourceData = sources:interpolate(raster_source, source.lon, source.lat)
|
local sourceData = sources:interpolate(raster_source, source.lon, source.lat)
|
||||||
local targetData = sources:interpolate(raster_source, target.lon, target.lat)
|
local targetData = sources:interpolate(raster_source, target.lon, target.lat)
|
||||||
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
|
|
||||||
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
||||||
print (" slope: " .. slope)
|
io.write(" slope: " .. slope .. "\n")
|
||||||
print (" was speed: " .. weight.speed)
|
io.write(" was speed: " .. weight.speed .. "\n")
|
||||||
|
|
||||||
weight.speed = weight.speed * (1 - (slope * 5))
|
weight.speed = weight.speed * (1 - (slope * 5))
|
||||||
print (" new speed: " .. weight.speed)
|
io.write(" new speed: " .. weight.speed .. "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,15 +32,15 @@ end
|
|||||||
function segment_function (source, target, distance, weight)
|
function segment_function (source, target, distance, weight)
|
||||||
local sourceData = sources:query(raster_source, source.lon, source.lat)
|
local sourceData = sources:query(raster_source, source.lon, source.lat)
|
||||||
local targetData = sources:query(raster_source, target.lon, target.lat)
|
local targetData = sources:query(raster_source, target.lon, target.lat)
|
||||||
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
|
|
||||||
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
||||||
print (" slope: " .. slope)
|
io.write(" slope: " .. slope .. "\n")
|
||||||
print (" was speed: " .. weight.speed)
|
io.write(" was speed: " .. weight.speed .. "\n")
|
||||||
|
|
||||||
weight.speed = weight.speed * (1 - (slope * 5))
|
weight.speed = weight.speed * (1 - (slope * 5))
|
||||||
print (" new speed: " .. weight.speed)
|
io.write(" new speed: " .. weight.speed .. "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ speed_profile = {
|
|||||||
|
|
||||||
-- these settings are read directly by osrm
|
-- these settings are read directly by osrm
|
||||||
|
|
||||||
take_minimum_of_speeds = true
|
properties.allow_u_turn_at_via = false
|
||||||
obey_oneway = true
|
properties.use_turn_restrictions = true
|
||||||
obey_barriers = true
|
properties.traffic_signal_penalty = 7 -- seconds
|
||||||
use_turn_restrictions = true
|
properties.u_turn_penalty = 20
|
||||||
ignore_areas = true -- future feature
|
|
||||||
traffic_signal_penalty = 7 -- seconds
|
|
||||||
u_turn_penalty = 20
|
|
||||||
|
|
||||||
function limit_speed(speed, limits)
|
function limit_speed(speed, limits)
|
||||||
-- don't use ipairs(), since it stops at the first nil value
|
-- don't use ipairs(), since it stops at the first nil value
|
||||||
|
|||||||
@@ -173,6 +173,10 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
|
|||||||
std::unordered_map<std::pair<OSMNodeID, OSMNodeID>, std::pair<unsigned, uint8_t>>
|
std::unordered_map<std::pair<OSMNodeID, OSMNodeID>, std::pair<unsigned, uint8_t>>
|
||||||
segment_speed_lookup;
|
segment_speed_lookup;
|
||||||
|
|
||||||
|
// If we update the edge weights, this file will hold the datasource information
|
||||||
|
// for each segment
|
||||||
|
std::vector<uint8_t> m_geometry_datasource;
|
||||||
|
|
||||||
if (update_edge_weights)
|
if (update_edge_weights)
|
||||||
{
|
{
|
||||||
uint8_t file_id = 1;
|
uint8_t file_id = 1;
|
||||||
@@ -264,7 +268,7 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
|
|||||||
// CSV file that supplied the value that gets used for that segment, then
|
// CSV file that supplied the value that gets used for that segment, then
|
||||||
// we write out this list so that it can be returned by the debugging
|
// we write out this list so that it can be returned by the debugging
|
||||||
// vector tiles later on.
|
// vector tiles later on.
|
||||||
std::vector<uint8_t> m_geometry_datasource(m_geometry_list.size(), 0);
|
m_geometry_datasource.resize(m_geometry_list.size(), 0);
|
||||||
|
|
||||||
// Now, we iterate over all the segments stored in the StaticRTree, updating
|
// Now, we iterate over all the segments stored in the StaticRTree, updating
|
||||||
// the packed geometry weights in the `.geometries` file (note: we do not
|
// the packed geometry weights in the `.geometries` file (note: we do not
|
||||||
@@ -402,33 +406,36 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
|
|||||||
number_of_compressed_geometries *
|
number_of_compressed_geometries *
|
||||||
sizeof(extractor::CompressedEdgeContainer::CompressedEdge));
|
sizeof(extractor::CompressedEdgeContainer::CompressedEdge));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ofstream datasource_stream(datasource_indexes_filename, std::ios::binary);
|
||||||
|
if (!datasource_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Failed to open " + datasource_indexes_filename +
|
||||||
|
" for writing");
|
||||||
|
}
|
||||||
|
auto number_of_datasource_entries = m_geometry_datasource.size();
|
||||||
|
datasource_stream.write(reinterpret_cast<const char *>(&number_of_datasource_entries),
|
||||||
|
sizeof(number_of_datasource_entries));
|
||||||
|
if (number_of_datasource_entries > 0)
|
||||||
{
|
{
|
||||||
std::ofstream datasource_stream(datasource_indexes_filename, std::ios::binary);
|
|
||||||
if (!datasource_stream)
|
|
||||||
{
|
|
||||||
throw util::exception("Failed to open " + datasource_indexes_filename +
|
|
||||||
" for writing");
|
|
||||||
}
|
|
||||||
auto number_of_datasource_entries = m_geometry_datasource.size();
|
|
||||||
datasource_stream.write(reinterpret_cast<const char *>(&number_of_datasource_entries),
|
|
||||||
sizeof(number_of_datasource_entries));
|
|
||||||
datasource_stream.write(reinterpret_cast<char *>(&(m_geometry_datasource[0])),
|
datasource_stream.write(reinterpret_cast<char *>(&(m_geometry_datasource[0])),
|
||||||
number_of_datasource_entries * sizeof(uint8_t));
|
number_of_datasource_entries * sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ofstream datasource_stream(datasource_names_filename, std::ios::binary);
|
||||||
|
if (!datasource_stream)
|
||||||
{
|
{
|
||||||
std::ofstream datasource_stream(datasource_names_filename, std::ios::binary);
|
throw util::exception("Failed to open " + datasource_names_filename +
|
||||||
if (!datasource_stream)
|
" for writing");
|
||||||
{
|
}
|
||||||
throw util::exception("Failed to open " + datasource_names_filename +
|
datasource_stream << "lua profile" << std::endl;
|
||||||
" for writing");
|
for (auto const &name : segment_speed_filenames)
|
||||||
}
|
{
|
||||||
datasource_stream << "lua profile" << std::endl;
|
datasource_stream << name << std::endl;
|
||||||
for (auto const &name : segment_speed_filenames)
|
|
||||||
{
|
|
||||||
datasource_stream << name << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ const constexpr char *modifier_names[] = {"uturn",
|
|||||||
// translations of TurnTypes. Not all types are exposed to the outside world.
|
// translations of TurnTypes. Not all types are exposed to the outside world.
|
||||||
// invalid types should never be returned as part of the API
|
// invalid types should never be returned as part of the API
|
||||||
const constexpr char *turn_type_names[] = {
|
const constexpr char *turn_type_names[] = {
|
||||||
"invalid", "no turn", "invalid", "new name", "continue", "turn",
|
"invalid", "no turn", "invalid", "new name", "continue", "turn",
|
||||||
"merge", "ramp", "fork", "end of road", "roundabout", "invalid",
|
"turn", "turn", "turn", "turn", "merge", "ramp",
|
||||||
"roundabout", "invalid", "traffic circle", "invalid", "traffic circle", "invalid",
|
"ramp", "ramp", "ramp", "ramp", "fork", "end of road",
|
||||||
"invalid", "restriction", "notification"};
|
"roundabout", "invalid", "roundabout", "invalid", "traffic circle", "invalid",
|
||||||
|
"traffic circle", "invalid", "invalid", "restriction", "notification"};
|
||||||
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
|
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
|
||||||
|
|
||||||
// Check whether to include a modifier in the result of the API
|
// Check whether to include a modifier in the result of the API
|
||||||
@@ -149,6 +149,12 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
|||||||
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
|
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
|
||||||
if (maneuver.exit != 0)
|
if (maneuver.exit != 0)
|
||||||
step_maneuver.values["exit"] = maneuver.exit;
|
step_maneuver.values["exit"] = maneuver.exit;
|
||||||
|
|
||||||
|
// TODO currently we need this to comply with the api.
|
||||||
|
// We should move this to an additional entry, the moment we
|
||||||
|
// actually compute the correct locations of the intersections
|
||||||
|
if (!maneuver.intersections.empty() && maneuver.exit == 0)
|
||||||
|
step_maneuver.values["exit"] = maneuver.intersections.size();
|
||||||
return step_maneuver;
|
return step_maneuver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,28 +27,30 @@ struct CoordinatePairCalculator
|
|||||||
CoordinatePairCalculator(const util::Coordinate coordinate_a,
|
CoordinatePairCalculator(const util::Coordinate coordinate_a,
|
||||||
const util::Coordinate coordinate_b)
|
const util::Coordinate coordinate_b)
|
||||||
{
|
{
|
||||||
|
using namespace util::coordinate_calculation;
|
||||||
// initialize distance calculator with two fixed coordinates a, b
|
// initialize distance calculator with two fixed coordinates a, b
|
||||||
first_lon = static_cast<double>(toFloating(coordinate_a.lon)) * util::RAD;
|
first_lon = static_cast<double>(toFloating(coordinate_a.lon)) * DEGREE_TO_RAD;
|
||||||
first_lat = static_cast<double>(toFloating(coordinate_a.lat)) * util::RAD;
|
first_lat = static_cast<double>(toFloating(coordinate_a.lat)) * DEGREE_TO_RAD;
|
||||||
second_lon = static_cast<double>(toFloating(coordinate_b.lon)) * util::RAD;
|
second_lon = static_cast<double>(toFloating(coordinate_b.lon)) * DEGREE_TO_RAD;
|
||||||
second_lat = static_cast<double>(toFloating(coordinate_b.lat)) * util::RAD;
|
second_lat = static_cast<double>(toFloating(coordinate_b.lat)) * DEGREE_TO_RAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operator()(const util::Coordinate other) const
|
int operator()(const util::Coordinate other) const
|
||||||
{
|
{
|
||||||
|
using namespace util::coordinate_calculation;
|
||||||
// set third coordinate c
|
// set third coordinate c
|
||||||
const float float_lon1 = static_cast<double>(toFloating(other.lon)) * util::RAD;
|
const float float_lon1 = static_cast<double>(toFloating(other.lon)) * DEGREE_TO_RAD;
|
||||||
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * util::RAD;
|
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * DEGREE_TO_RAD;
|
||||||
|
|
||||||
// compute distance (a,c)
|
// compute distance (a,c)
|
||||||
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
||||||
const float y_value_1 = first_lat - float_lat1;
|
const float y_value_1 = first_lat - float_lat1;
|
||||||
const float dist1 = std::hypot(x_value_1, y_value_1) * util::EARTH_RADIUS;
|
const float dist1 = std::hypot(x_value_1, y_value_1) * EARTH_RADIUS;
|
||||||
|
|
||||||
// compute distance (b,c)
|
// compute distance (b,c)
|
||||||
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
||||||
const float y_value_2 = second_lat - float_lat1;
|
const float y_value_2 = second_lat - float_lat1;
|
||||||
const float dist2 = std::hypot(x_value_2, y_value_2) * util::EARTH_RADIUS;
|
const float dist2 = std::hypot(x_value_2, y_value_2) * EARTH_RADIUS;
|
||||||
|
|
||||||
// return the minimum
|
// return the minimum
|
||||||
return static_cast<int>(std::min(dist1, dist2));
|
return static_cast<int>(std::min(dist1, dist2));
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include "storage/shared_barriers.hpp"
|
#include "storage/shared_barriers.hpp"
|
||||||
#include "util/make_unique.hpp"
|
#include "util/make_unique.hpp"
|
||||||
#include "util/routed_options.hpp"
|
|
||||||
#include "util/simple_logger.hpp"
|
#include "util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -136,8 +135,11 @@ Engine::Engine(EngineConfig &config)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
util::populate_base_path(config.server_paths);
|
if (!config.storage_config.IsValid())
|
||||||
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.server_paths);
|
{
|
||||||
|
throw util::exception("Invalid file paths given!");
|
||||||
|
}
|
||||||
|
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.storage_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register plugins
|
// Register plugins
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include "engine/engine_config.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
|
||||||
|
bool EngineConfig::IsValid() const
|
||||||
|
{
|
||||||
|
const bool all_path_are_empty =
|
||||||
|
storage_config.ram_index_path.empty() && storage_config.file_index_path.empty() &&
|
||||||
|
storage_config.hsgr_data_path.empty() && storage_config.nodes_data_path.empty() &&
|
||||||
|
storage_config.edges_data_path.empty() && storage_config.core_data_path.empty() &&
|
||||||
|
storage_config.geometries_path.empty() && storage_config.timestamp_path.empty() &&
|
||||||
|
storage_config.datasource_names_path.empty() &&
|
||||||
|
storage_config.datasource_indexes_path.empty() && storage_config.names_data_path.empty();
|
||||||
|
|
||||||
|
const bool limits_valid =
|
||||||
|
(max_locations_distance_table == -1 || max_locations_distance_table > 2) &&
|
||||||
|
(max_locations_map_matching == -1 || max_locations_map_matching > 2) &&
|
||||||
|
(max_locations_trip == -1 || max_locations_trip > 2) &&
|
||||||
|
(max_locations_viaroute == -1 || max_locations_viaroute > 2);
|
||||||
|
|
||||||
|
return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "engine/guidance/leg_geometry.hpp"
|
#include "engine/guidance/leg_geometry.hpp"
|
||||||
#include "engine/douglas_peucker.hpp"
|
#include "engine/douglas_peucker.hpp"
|
||||||
#include "util/tiles.hpp"
|
#include "util/viewport.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
@@ -23,25 +23,22 @@ namespace
|
|||||||
|
|
||||||
unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometries)
|
unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometries)
|
||||||
{
|
{
|
||||||
util::FixedLongitude min_lon{std::numeric_limits<int>::max()};
|
util::Coordinate south_west{util::FixedLongitude{std::numeric_limits<int>::max()}, util::FixedLatitude{std::numeric_limits<int>::max()}};
|
||||||
util::FixedLongitude max_lon{std::numeric_limits<int>::min()};
|
util::Coordinate north_east{util::FixedLongitude{std::numeric_limits<int>::min()}, util::FixedLatitude{std::numeric_limits<int>::min()}};
|
||||||
util::FixedLatitude min_lat{std::numeric_limits<int>::max()};
|
|
||||||
util::FixedLatitude max_lat{std::numeric_limits<int>::min()};
|
|
||||||
|
|
||||||
for (const auto &leg_geometry : leg_geometries)
|
for (const auto &leg_geometry : leg_geometries)
|
||||||
{
|
{
|
||||||
for (const auto coord : leg_geometry.locations)
|
for (const auto coord : leg_geometry.locations)
|
||||||
{
|
{
|
||||||
min_lon = std::min(min_lon, coord.lon);
|
south_west.lon = std::min(south_west.lon, coord.lon);
|
||||||
max_lon = std::max(max_lon, coord.lon);
|
south_west.lat = std::min(south_west.lat, coord.lat);
|
||||||
min_lat = std::min(min_lat, coord.lat);
|
|
||||||
max_lat = std::max(max_lat, coord.lat);
|
north_east.lon = std::max(north_east.lon, coord.lon);
|
||||||
|
north_east.lat = std::max(north_east.lat, coord.lat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return util::tiles::getBBMaxZoomTile(toFloating(min_lon), toFloating(min_lat),
|
return util::viewport::getFittedZoom(south_west, north_east);
|
||||||
toFloating(max_lon), toFloating(max_lat))
|
|
||||||
.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<util::Coordinate> simplifyGeometry(const std::vector<LegGeometry> &leg_geometries,
|
std::vector<util::Coordinate> simplifyGeometry(const std::vector<LegGeometry> &leg_geometries,
|
||||||
@@ -70,7 +67,7 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
|
|||||||
{
|
{
|
||||||
if (use_simplification)
|
if (use_simplification)
|
||||||
{
|
{
|
||||||
const auto zoom_level = calculateOverviewZoomLevel(leg_geometries);
|
const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries));
|
||||||
return simplifyGeometry(leg_geometries, zoom_level);
|
return simplifyGeometry(leg_geometries, zoom_level);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(!use_simplification);
|
BOOST_ASSERT(!use_simplification);
|
||||||
|
|||||||
@@ -12,15 +12,49 @@ namespace guidance
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||||
const WaypointType waypoint_type,
|
const WaypointType waypoint_type,
|
||||||
|
const LegGeometry &leg_geometry)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(waypoint_type != WaypointType::None);
|
||||||
|
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||||
|
|
||||||
|
double pre_turn_bearing = 0, post_turn_bearing = 0;
|
||||||
|
Coordinate turn_coordinate;
|
||||||
|
if (waypoint_type == WaypointType::Arrive)
|
||||||
|
{
|
||||||
|
turn_coordinate = leg_geometry.locations.front();
|
||||||
|
const auto post_turn_coordinate = *(leg_geometry.locations.begin() + 1);
|
||||||
|
post_turn_bearing =
|
||||||
|
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(waypoint_type == WaypointType::Depart);
|
||||||
|
turn_coordinate = leg_geometry.locations.back();
|
||||||
|
const auto pre_turn_coordinate = *(leg_geometry.locations.end() - 2);
|
||||||
|
pre_turn_bearing =
|
||||||
|
util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate);
|
||||||
|
}
|
||||||
|
return StepManeuver{
|
||||||
|
std::move(turn_coordinate),
|
||||||
|
pre_turn_bearing,
|
||||||
|
post_turn_bearing,
|
||||||
|
std::move(instruction),
|
||||||
|
waypoint_type,
|
||||||
|
INVALID_EXIT_NR,
|
||||||
|
{} // no intermediate intersections
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||||
const LegGeometry &leg_geometry,
|
const LegGeometry &leg_geometry,
|
||||||
const std::size_t segment_index,
|
const std::size_t segment_index)
|
||||||
const unsigned exit)
|
|
||||||
{
|
{
|
||||||
auto turn_index = leg_geometry.BackIndex(segment_index);
|
auto turn_index = leg_geometry.BackIndex(segment_index);
|
||||||
BOOST_ASSERT(turn_index > 0);
|
BOOST_ASSERT(turn_index > 0);
|
||||||
BOOST_ASSERT(turn_index < leg_geometry.locations.size());
|
BOOST_ASSERT(turn_index + 1 < leg_geometry.locations.size());
|
||||||
|
|
||||||
// TODO chose a bigger look-a-head to smooth complex geometry
|
// TODO chose a bigger look-a-head to smooth complex geometry
|
||||||
const auto pre_turn_coordinate = leg_geometry.locations[turn_index - 1];
|
const auto pre_turn_coordinate = leg_geometry.locations[turn_index - 1];
|
||||||
@@ -32,7 +66,15 @@ StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instr
|
|||||||
const double post_turn_bearing =
|
const double post_turn_bearing =
|
||||||
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
|
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
|
||||||
|
|
||||||
return StepManeuver{turn_coordinate, pre_turn_bearing, post_turn_bearing, instruction, waypoint_type, exit};
|
return StepManeuver{
|
||||||
|
std::move(turn_coordinate),
|
||||||
|
pre_turn_bearing,
|
||||||
|
post_turn_bearing,
|
||||||
|
std::move(instruction),
|
||||||
|
WaypointType::None,
|
||||||
|
INVALID_EXIT_NR,
|
||||||
|
{} // no intermediate intersections
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} // ns detail
|
} // ns detail
|
||||||
} // ns engine
|
} // ns engine
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
#include "engine/guidance/toolkit.hpp"
|
#include "engine/guidance/toolkit.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <cstddef>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
|
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
|
||||||
using TurnType = osrm::extractor::guidance::TurnType;
|
using TurnType = osrm::extractor::guidance::TurnType;
|
||||||
@@ -20,196 +23,296 @@ namespace guidance
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
bool canMergeTrivially(const PathData &destination, const PathData &source)
|
bool canMergeTrivially(const RouteStep &destination, const RouteStep &source)
|
||||||
{
|
{
|
||||||
return destination.exit == 0 && destination.name_id == source.name_id &&
|
return destination.maneuver.exit == 0 && destination.name_id == source.name_id &&
|
||||||
destination.travel_mode == source.travel_mode && isSilent(source.turn_instruction);
|
isSilent(source.maneuver.instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathData forwardInto(PathData destination, const PathData &source)
|
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
||||||
{
|
{
|
||||||
// Merge a turn into a silent turn
|
// Merge a turn into a silent turn
|
||||||
// Overwrites turn instruction and increases exit NR
|
// Overwrites turn instruction and increases exit NR
|
||||||
destination.duration_until_turn += source.duration_until_turn;
|
destination.duration += source.duration;
|
||||||
destination.exit = source.exit;
|
destination.distance += source.distance;
|
||||||
|
destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin);
|
||||||
|
destination.geometry_end = std::max(destination.geometry_end, source.geometry_end);
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathData accumulateInto(PathData destination, const PathData &source)
|
void fixFinalRoundabout(std::vector<RouteStep> &steps)
|
||||||
{
|
{
|
||||||
// Merge a turn into a silent turn
|
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
|
||||||
// Overwrites turn instruction and increases exit NR
|
--propagation_index)
|
||||||
BOOST_ASSERT(canMergeTrivially(destination, source));
|
|
||||||
destination.duration_until_turn += source.duration_until_turn;
|
|
||||||
destination.exit = source.exit + 1;
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
PathData mergeInto(PathData destination, const PathData &source)
|
|
||||||
{
|
|
||||||
if (source.turn_instruction == TurnInstruction::NO_TURN())
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(canMergeTrivially(destination, source));
|
auto &propagation_step = steps[propagation_index];
|
||||||
return detail::forwardInto(destination, source);
|
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||||
}
|
|
||||||
if (source.turn_instruction.type == TurnType::Suppressed)
|
|
||||||
{
|
|
||||||
return detail::forwardInto(destination, source);
|
|
||||||
}
|
|
||||||
if (source.turn_instruction.type == TurnType::StayOnRoundabout)
|
|
||||||
{
|
|
||||||
return detail::forwardInto(destination, source);
|
|
||||||
}
|
|
||||||
if (entersRoundabout(source.turn_instruction))
|
|
||||||
{
|
|
||||||
return detail::forwardInto(destination, source);
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
void print(const std::vector<std::vector<PathData>> &leg_data)
|
|
||||||
{
|
|
||||||
std::cout << "Path\n";
|
|
||||||
int legnr = 0;
|
|
||||||
for (const auto &leg : leg_data)
|
|
||||||
{
|
|
||||||
std::cout << "\tLeg: " << ++legnr << "\n";
|
|
||||||
int segment = 0;
|
|
||||||
for (const auto &data : leg)
|
|
||||||
{
|
{
|
||||||
const auto type = static_cast<int>(data.turn_instruction.type);
|
propagation_step.maneuver.exit = 0;
|
||||||
const auto modifier = static_cast<int>(data.turn_instruction.direction_modifier);
|
propagation_step.geometry_end = steps.back().geometry_begin;
|
||||||
|
break;
|
||||||
std::cout << "\t\t[" << ++segment << "]: " << type << " " << modifier
|
}
|
||||||
<< " exit: " << data.exit << "\n";
|
else if (propagation_step.maneuver.instruction.type == TurnType::StayOnRoundabout)
|
||||||
|
{
|
||||||
|
// TODO this operates on the data that is in the instructions.
|
||||||
|
// We are missing out on the final segment after the last stay-on-roundabout
|
||||||
|
// instruction though. it is not contained somewhere until now
|
||||||
|
steps[propagation_index - 1] =
|
||||||
|
forwardInto(std::move(steps[propagation_index - 1]), propagation_step);
|
||||||
|
propagation_step.maneuver.instruction =
|
||||||
|
TurnInstruction::NO_TURN(); // mark intermediate instructions invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
|
bool setUpRoundabout(RouteStep &step)
|
||||||
{
|
{
|
||||||
if (leg_data.empty())
|
// basic entry into a roundabout
|
||||||
return leg_data;
|
// Special case handling, if an entry is directly tied to an exit
|
||||||
|
const auto instruction = step.maneuver.instruction;
|
||||||
|
if (instruction.type == TurnType::EnterRotaryAtExit ||
|
||||||
|
instruction.type == TurnType::EnterRoundaboutAtExit)
|
||||||
|
{
|
||||||
|
step.maneuver.exit = 1;
|
||||||
|
// prevent futher special case handling of these two.
|
||||||
|
if (instruction.type == TurnType::EnterRotaryAtExit)
|
||||||
|
step.maneuver.instruction = TurnType::EnterRotary;
|
||||||
|
else
|
||||||
|
step.maneuver.instruction = TurnType::EnterRoundabout;
|
||||||
|
}
|
||||||
|
|
||||||
#define PRINT_DEBUG 0
|
if (leavesRoundabout(instruction))
|
||||||
unsigned carry_exit = 0;
|
{
|
||||||
#if PRINT_DEBUG
|
step.maneuver.exit = 1; // count the otherwise missing exit
|
||||||
|
if (instruction.type == TurnType::EnterRotaryAtExit)
|
||||||
|
step.maneuver.instruction = TurnType::EnterRotary;
|
||||||
|
else
|
||||||
|
step.maneuver.instruction = TurnType::EnterRoundabout;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeOffRoundabout(const bool on_roundabout,
|
||||||
|
std::vector<RouteStep> &steps,
|
||||||
|
const std::size_t step_index)
|
||||||
|
{
|
||||||
|
auto &step = steps[step_index];
|
||||||
|
step.maneuver.exit += 1;
|
||||||
|
if (!on_roundabout)
|
||||||
|
{
|
||||||
|
|
||||||
|
// We reached a special case that requires the addition of a special route step in
|
||||||
|
// the beginning.
|
||||||
|
// We started in a roundabout, so to announce the exit, we move use the exit
|
||||||
|
// instruction and
|
||||||
|
// move it right to the beginning to make sure to immediately announce the exit.
|
||||||
|
BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) ||
|
||||||
|
steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout);
|
||||||
|
steps[0].geometry_end = 1;
|
||||||
|
steps[1] = detail::forwardInto(steps[1], steps[0]);
|
||||||
|
steps[0].duration = 0;
|
||||||
|
steps[0].distance = 0;
|
||||||
|
steps[1].maneuver.instruction.type = step.maneuver.instruction.type == TurnType::ExitRotary
|
||||||
|
? TurnType::EnterRotary
|
||||||
|
: TurnType::EnterRoundabout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal exit from the roundabout, or exit from a previously fixed roundabout.
|
||||||
|
// Propagate the index back to the entering
|
||||||
|
// location and
|
||||||
|
// prepare the current silent set of instructions for removal.
|
||||||
|
if (step_index > 1)
|
||||||
|
{
|
||||||
|
// The very first route-step is head, so we cannot iterate past that one
|
||||||
|
for (std::size_t propagation_index = step_index - 1; propagation_index > 0;
|
||||||
|
--propagation_index)
|
||||||
|
{
|
||||||
|
auto &propagation_step = steps[propagation_index];
|
||||||
|
propagation_step = detail::forwardInto(propagation_step, steps[propagation_index + 1]);
|
||||||
|
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||||
|
{
|
||||||
|
// TODO at this point, we can remember the additional name for a rotary
|
||||||
|
// This requires some initial thought on the data format, though
|
||||||
|
propagation_step.maneuver.exit = step.maneuver.exit;
|
||||||
|
propagation_step.geometry_end = step.geometry_end;
|
||||||
|
propagation_step.name = step.name;
|
||||||
|
propagation_step.name_id = step.name_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(propagation_step.maneuver.instruction.type =
|
||||||
|
TurnType::StayOnRoundabout);
|
||||||
|
propagation_step.maneuver.instruction =
|
||||||
|
TurnInstruction::NO_TURN(); // mark intermediate instructions invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove exit
|
||||||
|
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
void print(const std::vector<RouteStep> &steps)
|
||||||
|
{
|
||||||
|
std::cout << "Path\n";
|
||||||
|
int segment = 0;
|
||||||
|
for (const auto &step : steps)
|
||||||
|
{
|
||||||
|
const auto type = static_cast<int>(step.maneuver.instruction.type);
|
||||||
|
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
|
||||||
|
|
||||||
|
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
||||||
|
<< " Duration: " << step.duration << " Distance: " << step.distance
|
||||||
|
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
|
||||||
|
<< " exit: " << step.maneuver.exit
|
||||||
|
<< " Intersections: " << step.maneuver.intersections.size() << " [";
|
||||||
|
|
||||||
|
for (auto intersection : step.maneuver.intersections)
|
||||||
|
std::cout << "(" << intersection.duration << " " << intersection.distance << ")";
|
||||||
|
|
||||||
|
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Step Maneuver consists of the information until the turn.
|
||||||
|
// This list contains a set of instructions, called silent, which should
|
||||||
|
// not be part of the final output.
|
||||||
|
// They are required for maintenance purposes. We can calculate the number
|
||||||
|
// of exits to pass in a roundabout and the number of intersections
|
||||||
|
// that we come across.
|
||||||
|
|
||||||
|
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
||||||
|
{
|
||||||
|
// the steps should always include the first/last step in form of a location
|
||||||
|
BOOST_ASSERT(steps.size() >= 2);
|
||||||
|
if (steps.size() == 2)
|
||||||
|
return steps;
|
||||||
|
|
||||||
|
#define OSRM_POST_PROCESSING_PRINT_DEBUG 0
|
||||||
|
#if OSRM_POST_PROCESSING_PRINT_DEBUG
|
||||||
std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
|
std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
|
||||||
std::cout << "Input\n";
|
std::cout << "Input\n";
|
||||||
print(leg_data);
|
print(steps);
|
||||||
#endif
|
#endif
|
||||||
// Count Street Exits forward
|
// Count Street Exits forward
|
||||||
bool on_roundabout = false;
|
bool on_roundabout = false;
|
||||||
for (auto &path_data : leg_data)
|
|
||||||
|
// adds an intersection to the initial route step
|
||||||
|
// It includes the length of the last step, until the intersection
|
||||||
|
// Also updates the length of the respective segment
|
||||||
|
auto addIntersection =
|
||||||
|
[](RouteStep into, const RouteStep &last_step, const RouteStep &intersection)
|
||||||
{
|
{
|
||||||
if (not path_data.empty())
|
into.maneuver.intersections.push_back(
|
||||||
path_data[0].exit = carry_exit;
|
{last_step.duration, last_step.distance, intersection.maneuver.location});
|
||||||
|
|
||||||
for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
|
return detail::forwardInto(std::move(into), intersection);
|
||||||
|
};
|
||||||
|
|
||||||
|
// count the exits forward. if enter/exit roundabout happen both, no further treatment is
|
||||||
|
// required. We might end up with only one of them (e.g. starting within a roundabout)
|
||||||
|
// or having a via-point in the roundabout.
|
||||||
|
// In this case, exits are numbered from the start of the lag.
|
||||||
|
std::size_t last_valid_instruction = 0;
|
||||||
|
for (std::size_t step_index = 0; step_index < steps.size(); ++step_index)
|
||||||
|
{
|
||||||
|
auto &step = steps[step_index];
|
||||||
|
const auto instruction = step.maneuver.instruction;
|
||||||
|
if (entersRoundabout(instruction))
|
||||||
{
|
{
|
||||||
if (entersRoundabout(path_data[data_index].turn_instruction))
|
last_valid_instruction = step_index;
|
||||||
|
on_roundabout = detail::setUpRoundabout(step);
|
||||||
|
if (on_roundabout && step_index + 1 < steps.size())
|
||||||
|
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
|
||||||
|
}
|
||||||
|
else if (instruction.type == TurnType::StayOnRoundabout)
|
||||||
|
{
|
||||||
|
// increase the exit number we require passing the exit
|
||||||
|
step.maneuver.exit += 1;
|
||||||
|
if (step_index + 1 < steps.size())
|
||||||
|
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
|
||||||
|
}
|
||||||
|
else if (leavesRoundabout(instruction))
|
||||||
|
{
|
||||||
|
if (!on_roundabout)
|
||||||
{
|
{
|
||||||
path_data[data_index].exit += 1;
|
// in case the we are not on a roundabout, the very first instruction
|
||||||
on_roundabout = true;
|
// after the depart will be transformed into a roundabout and become
|
||||||
|
// the first valid instruction
|
||||||
|
last_valid_instruction = 1;
|
||||||
}
|
}
|
||||||
|
detail::closeOffRoundabout(on_roundabout, steps, step_index);
|
||||||
if (isSilent(path_data[data_index].turn_instruction) &&
|
on_roundabout = false;
|
||||||
path_data[data_index].turn_instruction != TurnInstruction::NO_TURN())
|
}
|
||||||
{
|
else if (instruction.type == TurnType::Suppressed)
|
||||||
path_data[data_index].exit += 1;
|
{
|
||||||
}
|
// count intersections. We cannot use exit, since intersections can follow directly
|
||||||
if (leavesRoundabout(path_data[data_index].turn_instruction))
|
// after a roundabout
|
||||||
{
|
steps[last_valid_instruction] = addIntersection(
|
||||||
if (!on_roundabout)
|
std::move(steps[last_valid_instruction]), steps[step_index - 1], step);
|
||||||
{
|
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
BOOST_ASSERT(leg_data[0][0].turn_instruction.type ==
|
}
|
||||||
TurnInstruction::NO_TURN());
|
else if (!isSilent(instruction))
|
||||||
if (path_data[data_index].turn_instruction.type == TurnType::ExitRoundabout)
|
{
|
||||||
leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
|
// Remember the last non silent instruction
|
||||||
if (path_data[data_index].turn_instruction.type == TurnType::ExitRotary)
|
last_valid_instruction = step_index;
|
||||||
leg_data[0][0].turn_instruction.type = TurnType::EnterRotary;
|
|
||||||
path_data[data_index].exit += 1;
|
|
||||||
}
|
|
||||||
on_roundabout = false;
|
|
||||||
}
|
|
||||||
if (path_data[data_index].turn_instruction.type == TurnType::EnterRoundaboutAtExit)
|
|
||||||
{
|
|
||||||
path_data[data_index].exit += 1;
|
|
||||||
path_data[data_index].turn_instruction.type = TurnType::EnterRoundabout;
|
|
||||||
}
|
|
||||||
else if (path_data[data_index].turn_instruction.type == TurnType::EnterRotaryAtExit)
|
|
||||||
{
|
|
||||||
path_data[data_index].exit += 1;
|
|
||||||
path_data[data_index].turn_instruction.type = TurnType::EnterRotary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSilent(path_data[data_index].turn_instruction) ||
|
|
||||||
entersRoundabout(path_data[data_index].turn_instruction))
|
|
||||||
{
|
|
||||||
path_data[data_index + 1] =
|
|
||||||
detail::mergeInto(path_data[data_index + 1], path_data[data_index]);
|
|
||||||
}
|
|
||||||
carry_exit = path_data[data_index].exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if PRINT_DEBUG
|
// unterminated roundabout
|
||||||
|
// Move backwards through the instructions until the start and remove the exit number
|
||||||
|
// A roundabout without exit translates to enter-roundabout.
|
||||||
|
if (on_roundabout)
|
||||||
|
{
|
||||||
|
detail::fixFinalRoundabout(steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally clean up the post-processed instructions.
|
||||||
|
// Remove all invalid instructions from the set of instructions.
|
||||||
|
// An instruction is invalid, if its NO_TURN and has WaypointType::None.
|
||||||
|
// Two valid NO_TURNs exist in each leg in the form of Depart/Arrive
|
||||||
|
|
||||||
|
// keep valid instructions
|
||||||
|
const auto not_is_valid = [](const RouteStep &step)
|
||||||
|
{
|
||||||
|
return step.maneuver.instruction == TurnInstruction::NO_TURN() &&
|
||||||
|
step.maneuver.waypoint_type == WaypointType::None;
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::remove_erase_if(steps, not_is_valid);
|
||||||
|
|
||||||
|
#if OSRM_POST_PROCESSING_PRINT_DEBUG
|
||||||
std::cout << "Merged\n";
|
std::cout << "Merged\n";
|
||||||
print(leg_data);
|
print(steps);
|
||||||
#endif
|
#endif
|
||||||
on_roundabout = false;
|
return steps;
|
||||||
// Move Roundabout exit numbers to front
|
}
|
||||||
for (auto rev_itr = leg_data.rbegin(); rev_itr != leg_data.rend(); ++rev_itr)
|
|
||||||
|
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps)
|
||||||
|
{
|
||||||
|
// The geometry uses an adjacency array-like structure for representation.
|
||||||
|
// To sync it back up with the steps, we cann add a segment for every step.
|
||||||
|
leg_geometry.segment_offsets.clear();
|
||||||
|
leg_geometry.segment_distances.clear();
|
||||||
|
leg_geometry.segment_offsets.push_back(0);
|
||||||
|
|
||||||
|
for (const auto &step : steps)
|
||||||
{
|
{
|
||||||
auto &path_data = *rev_itr;
|
leg_geometry.segment_distances.push_back(step.distance);
|
||||||
for (std::size_t data_index = path_data.size(); data_index > 1; --data_index)
|
// the leg geometry does not follow the begin/end-convetion. So we have to subtract one
|
||||||
{
|
// to get the back-index.
|
||||||
if (entersRoundabout(path_data[data_index - 1].turn_instruction))
|
leg_geometry.segment_offsets.push_back(step.geometry_end - 1);
|
||||||
{
|
|
||||||
if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction))
|
|
||||||
path_data[data_index - 1].exit = 0;
|
|
||||||
on_roundabout = false;
|
|
||||||
}
|
|
||||||
if (on_roundabout)
|
|
||||||
{
|
|
||||||
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
|
||||||
}
|
|
||||||
if (leavesRoundabout(path_data[data_index - 1].turn_instruction) &&
|
|
||||||
!entersRoundabout(path_data[data_index - 1].turn_instruction))
|
|
||||||
{
|
|
||||||
path_data[data_index - 2].exit = path_data[data_index - 1].exit;
|
|
||||||
on_roundabout = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto prev_leg = std::next(rev_itr);
|
|
||||||
if (!path_data.empty() && prev_leg != leg_data.rend())
|
|
||||||
{
|
|
||||||
if (on_roundabout && path_data[0].exit)
|
|
||||||
prev_leg->back().exit = path_data[0].exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PRINT_DEBUG
|
//remove the data fromt the reached-target step again
|
||||||
std::cout << "Move To Front\n";
|
leg_geometry.segment_offsets.pop_back();
|
||||||
print(leg_data);
|
leg_geometry.segment_distances.pop_back();
|
||||||
#endif
|
|
||||||
// silence silent turns for good
|
|
||||||
for (auto &path_data : leg_data)
|
|
||||||
{
|
|
||||||
for (auto &data : path_data)
|
|
||||||
{
|
|
||||||
if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) &&
|
|
||||||
!entersRoundabout(data.turn_instruction)))
|
|
||||||
{
|
|
||||||
data.turn_instruction = TurnInstruction::NO_TURN();
|
|
||||||
data.exit = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return leg_data;
|
return leg_geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
|||||||
+45
-5
@@ -1,20 +1,60 @@
|
|||||||
#include "engine/hint.hpp"
|
#include "engine/hint.hpp"
|
||||||
#include "engine/object_encoder.hpp"
|
#include "engine/base64.hpp"
|
||||||
|
#include "engine/datafacade/datafacade_base.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ostream>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
std::string Hint::ToBase64() const { return encodeBase64(*this); }
|
|
||||||
|
bool Hint::IsValid(const util::Coordinate new_input_coordinates,
|
||||||
|
const datafacade::BaseDataFacade &facade) const
|
||||||
|
{
|
||||||
|
auto is_same_input_coordinate = new_input_coordinates.lon == phantom.input_location.lon &&
|
||||||
|
new_input_coordinates.lat == phantom.input_location.lat;
|
||||||
|
return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) &&
|
||||||
|
facade.GetCheckSum() == data_checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Hint::ToBase64() const
|
||||||
|
{
|
||||||
|
auto base64 = encodeBase64Bytewise(*this);
|
||||||
|
|
||||||
|
// Make safe for usage as GET parameter in URLs
|
||||||
|
std::replace(begin(base64), end(base64), '+', '-');
|
||||||
|
std::replace(begin(base64), end(base64), '/', '_');
|
||||||
|
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
Hint Hint::FromBase64(const std::string &base64Hint)
|
Hint Hint::FromBase64(const std::string &base64Hint)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(base64Hint.size() == ENCODED_HINT_SIZE, "Hint has invalid size");
|
BOOST_ASSERT_MSG(base64Hint.size() == ENCODED_HINT_SIZE, "Hint has invalid size");
|
||||||
|
|
||||||
auto decoded = decodeBase64<Hint>(base64Hint);
|
// We need mutability but don't want to change the API
|
||||||
return decoded;
|
auto encoded = base64Hint;
|
||||||
}
|
|
||||||
|
// Reverses above encoding we need for GET parameters in URL
|
||||||
|
std::replace(begin(encoded), end(encoded), '-', '+');
|
||||||
|
std::replace(begin(encoded), end(encoded), '_', '/');
|
||||||
|
|
||||||
|
return decodeBase64Bytewise<Hint>(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const Hint &lhs, const Hint &rhs)
|
||||||
|
{
|
||||||
|
return std::tie(lhs.phantom, lhs.data_checksum) ==
|
||||||
|
std::tie(rhs.phantom, rhs.data_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const Hint &hint) { return out << hint.ToBase64(); }
|
||||||
|
|
||||||
|
} // ns engine
|
||||||
|
} // ns osrm
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "engine/map_matching/bayes_classifier.hpp"
|
#include "engine/map_matching/bayes_classifier.hpp"
|
||||||
#include "engine/api/match_parameters.hpp"
|
#include "engine/api/match_parameters.hpp"
|
||||||
#include "engine/api/match_api.hpp"
|
#include "engine/api/match_api.hpp"
|
||||||
#include "engine/object_encoder.hpp"
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/json_logger.hpp"
|
#include "util/json_logger.hpp"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "engine/api/table_parameters.hpp"
|
#include "engine/api/table_parameters.hpp"
|
||||||
#include "engine/api/table_api.hpp"
|
#include "engine/api/table_api.hpp"
|
||||||
#include "engine/object_encoder.hpp"
|
|
||||||
#include "engine/routing_algorithms/many_to_many.hpp"
|
#include "engine/routing_algorithms/many_to_many.hpp"
|
||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
#include "util/string_util.hpp"
|
#include "util/string_util.hpp"
|
||||||
|
|||||||
+209
-187
@@ -1,6 +1,13 @@
|
|||||||
#include "engine/plugins/plugin_base.hpp"
|
#include "engine/plugins/plugin_base.hpp"
|
||||||
#include "engine/plugins/tile.hpp"
|
#include "engine/plugins/tile.hpp"
|
||||||
|
|
||||||
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
|
||||||
|
#include <boost/geometry.hpp>
|
||||||
|
#include <boost/geometry/geometries/point_xy.hpp>
|
||||||
|
#include <boost/geometry/geometries/geometries.hpp>
|
||||||
|
#include <boost/geometry/multi/geometries/multi_linestring.hpp>
|
||||||
|
|
||||||
#include <protozero/varint.hpp>
|
#include <protozero/varint.hpp>
|
||||||
#include <protozero/pbf_writer.hpp>
|
#include <protozero/pbf_writer.hpp>
|
||||||
|
|
||||||
@@ -17,89 +24,30 @@ namespace engine
|
|||||||
{
|
{
|
||||||
namespace plugins
|
namespace plugins
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Vector tiles are 4096 virtual pixels on each side
|
||||||
|
const constexpr double VECTOR_TILE_EXTENT = 4096.0;
|
||||||
|
const constexpr double VECTOR_TILE_BUFFER = 128.0;
|
||||||
|
|
||||||
// from mapnik/well_known_srs.hpp
|
// Simple container class for WSG84 coordinates
|
||||||
const constexpr double EARTH_RADIUS = 6378137.0;
|
template <typename T> struct Point final
|
||||||
const constexpr double EARTH_DIAMETER = EARTH_RADIUS * 2.0;
|
{
|
||||||
const constexpr double EARTH_CIRCUMFERENCE = EARTH_DIAMETER * M_PI;
|
Point(T _x, T _y) : x(_x), y(_y) {}
|
||||||
const constexpr double MAXEXTENT = EARTH_CIRCUMFERENCE / 2.0;
|
|
||||||
const constexpr double M_PI_by2 = M_PI / 2.0;
|
const T x;
|
||||||
const constexpr double D2R = M_PI / 180.0;
|
const T y;
|
||||||
const constexpr double R2D = 180.0 / M_PI;
|
};
|
||||||
const constexpr double M_PIby360 = M_PI / 360.0;
|
|
||||||
const constexpr double MAXEXTENTby180 = MAXEXTENT / 180.0;
|
|
||||||
const double MAX_LATITUDE = R2D * (2.0 * std::atan(std::exp(180.0 * D2R)) - M_PI_by2);
|
|
||||||
// ^ math functions are not constexpr since they have side-effects (setting errno) :(
|
|
||||||
|
|
||||||
// from mapnik-vector-tile
|
// from mapnik-vector-tile
|
||||||
namespace detail_pbf
|
namespace pbf
|
||||||
{
|
{
|
||||||
|
|
||||||
inline unsigned encode_length(const unsigned len) { return (len << 3u) | 2u; }
|
inline unsigned encode_length(const unsigned len) { return (len << 3u) | 2u; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a regular WSG84 lon/lat pair into
|
struct BBox final
|
||||||
// a mercator coordinate
|
|
||||||
inline void lonlat2merc(double &x, double &y)
|
|
||||||
{
|
{
|
||||||
if (x > 180)
|
BBox(const double _minx, const double _miny, const double _maxx, const double _maxy)
|
||||||
x = 180;
|
|
||||||
else if (x < -180)
|
|
||||||
x = -180;
|
|
||||||
if (y > MAX_LATITUDE)
|
|
||||||
y = MAX_LATITUDE;
|
|
||||||
else if (y < -MAX_LATITUDE)
|
|
||||||
y = -MAX_LATITUDE;
|
|
||||||
x = x * MAXEXTENTby180;
|
|
||||||
y = std::log(std::tan((90 + y) * M_PIby360)) * R2D;
|
|
||||||
y = y * MAXEXTENTby180;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the global default tile size for all Mapbox Vector Tiles
|
|
||||||
const constexpr double tile_size_ = 256.0;
|
|
||||||
|
|
||||||
//
|
|
||||||
inline void from_pixels(const double shift, double &x, double &y)
|
|
||||||
{
|
|
||||||
const double b = shift / 2.0;
|
|
||||||
x = (x - b) / (shift / 360.0);
|
|
||||||
const double g = (y - b) / -(shift / (2 * M_PI));
|
|
||||||
y = R2D * (2.0 * std::atan(std::exp(g)) - M_PI_by2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a WMS tile coordinate (z,x,y) into a mercator bounding box
|
|
||||||
inline void xyz2mercator(
|
|
||||||
const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy)
|
|
||||||
{
|
|
||||||
minx = x * tile_size_;
|
|
||||||
miny = (y + 1.0) * tile_size_;
|
|
||||||
maxx = (x + 1.0) * tile_size_;
|
|
||||||
maxy = y * tile_size_;
|
|
||||||
const double shift = std::pow(2.0, z) * tile_size_;
|
|
||||||
from_pixels(shift, minx, miny);
|
|
||||||
from_pixels(shift, maxx, maxy);
|
|
||||||
lonlat2merc(minx, miny);
|
|
||||||
lonlat2merc(maxx, maxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a WMS tile coordinate (z,x,y) into a wsg84 bounding box
|
|
||||||
inline void xyz2wsg84(
|
|
||||||
const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy)
|
|
||||||
{
|
|
||||||
minx = x * tile_size_;
|
|
||||||
miny = (y + 1.0) * tile_size_;
|
|
||||||
maxx = (x + 1.0) * tile_size_;
|
|
||||||
maxy = y * tile_size_;
|
|
||||||
const double shift = std::pow(2.0, z) * tile_size_;
|
|
||||||
from_pixels(shift, minx, miny);
|
|
||||||
from_pixels(shift, maxx, maxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// emulates mapbox::box2d, just a simple container for
|
|
||||||
// a box
|
|
||||||
struct bbox final
|
|
||||||
{
|
|
||||||
bbox(const double _minx, const double _miny, const double _maxx, const double _maxy)
|
|
||||||
: minx(_minx), miny(_miny), maxx(_maxx), maxy(_maxy)
|
: minx(_minx), miny(_miny), maxx(_maxx), maxy(_maxy)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -113,15 +61,6 @@ struct bbox final
|
|||||||
const double maxy;
|
const double maxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Simple container class for WSG84 coordinates
|
|
||||||
struct point_type_d final
|
|
||||||
{
|
|
||||||
point_type_d(double _x, double _y) : x(_x), y(_y) {}
|
|
||||||
|
|
||||||
const double x;
|
|
||||||
const double y;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Simple container for integer coordinates (i.e. pixel coords)
|
// Simple container for integer coordinates (i.e. pixel coords)
|
||||||
struct point_type_i final
|
struct point_type_i final
|
||||||
{
|
{
|
||||||
@@ -131,15 +70,23 @@ struct point_type_i final
|
|||||||
const std::int64_t y;
|
const std::int64_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
using line_type = std::vector<point_type_i>;
|
using FixedLine = std::vector<detail::Point<std::int32_t>>;
|
||||||
using line_typed = std::vector<point_type_d>;
|
using FloatLine = std::vector<detail::Point<double>>;
|
||||||
|
|
||||||
|
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> point_t;
|
||||||
|
typedef boost::geometry::model::linestring<point_t> linestring_t;
|
||||||
|
typedef boost::geometry::model::box<point_t> box_t;
|
||||||
|
typedef boost::geometry::model::multi_linestring<linestring_t> multi_linestring_t;
|
||||||
|
const static box_t clip_box(point_t(-detail::VECTOR_TILE_BUFFER, -detail::VECTOR_TILE_BUFFER),
|
||||||
|
point_t(detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER,
|
||||||
|
detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER));
|
||||||
|
|
||||||
// from mapnik-vector-tile
|
// from mapnik-vector-tile
|
||||||
// Encodes a linestring using protobuf zigzag encoding
|
// Encodes a linestring using protobuf zigzag encoding
|
||||||
inline bool encode_linestring(line_type line,
|
inline bool encodeLinestring(const FixedLine &line,
|
||||||
protozero::packed_field_uint32 &geometry,
|
protozero::packed_field_uint32 &geometry,
|
||||||
std::int32_t &start_x,
|
std::int32_t &start_x,
|
||||||
std::int32_t &start_y)
|
std::int32_t &start_y)
|
||||||
{
|
{
|
||||||
const std::size_t line_size = line.size();
|
const std::size_t line_size = line.size();
|
||||||
if (line_size < 2)
|
if (line_size < 2)
|
||||||
@@ -155,7 +102,7 @@ inline bool encode_linestring(line_type line,
|
|||||||
geometry.add_element(protozero::encode_zigzag32(pt->y - start_y));
|
geometry.add_element(protozero::encode_zigzag32(pt->y - start_y));
|
||||||
start_x = pt->x;
|
start_x = pt->x;
|
||||||
start_y = pt->y;
|
start_y = pt->y;
|
||||||
geometry.add_element(detail_pbf::encode_length(line_to_length));
|
geometry.add_element(detail::pbf::encode_length(line_to_length));
|
||||||
for (++pt; pt != line.end(); ++pt)
|
for (++pt; pt != line.end(); ++pt)
|
||||||
{
|
{
|
||||||
const std::int32_t dx = pt->x - start_x;
|
const std::int32_t dx = pt->x - start_x;
|
||||||
@@ -168,15 +115,65 @@ inline bool encode_linestring(line_type line,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FixedLine coordinatesToTileLine(const util::Coordinate start,
|
||||||
|
const util::Coordinate target,
|
||||||
|
const detail::BBox &tile_bbox)
|
||||||
|
{
|
||||||
|
using namespace util::coordinate_calculation;
|
||||||
|
FloatLine geo_line;
|
||||||
|
geo_line.emplace_back(static_cast<double>(util::toFloating(start.lon)),
|
||||||
|
static_cast<double>(util::toFloating(start.lat)));
|
||||||
|
geo_line.emplace_back(static_cast<double>(util::toFloating(target.lon)),
|
||||||
|
static_cast<double>(util::toFloating(target.lat)));
|
||||||
|
|
||||||
|
linestring_t unclipped_line;
|
||||||
|
|
||||||
|
for (auto const &pt : geo_line)
|
||||||
|
{
|
||||||
|
double px_merc = pt.x * mercator::DEGREE_TO_PX;
|
||||||
|
double py_merc = mercator::latToY(util::FloatLatitude(pt.y)) * mercator::DEGREE_TO_PX;
|
||||||
|
// convert lon/lat to tile coordinates
|
||||||
|
const auto px = std::round(
|
||||||
|
((px_merc - tile_bbox.minx) * mercator::TILE_SIZE / tile_bbox.width()) *
|
||||||
|
detail::VECTOR_TILE_EXTENT / util::coordinate_calculation::mercator::TILE_SIZE);
|
||||||
|
const auto py = std::round(
|
||||||
|
((tile_bbox.maxy - py_merc) * mercator::TILE_SIZE / tile_bbox.height()) *
|
||||||
|
detail::VECTOR_TILE_EXTENT / util::coordinate_calculation::mercator::TILE_SIZE);
|
||||||
|
|
||||||
|
boost::geometry::append(unclipped_line, point_t(px, py));
|
||||||
|
}
|
||||||
|
|
||||||
|
multi_linestring_t clipped_line;
|
||||||
|
|
||||||
|
boost::geometry::intersection(clip_box, unclipped_line, clipped_line);
|
||||||
|
|
||||||
|
FixedLine tile_line;
|
||||||
|
|
||||||
|
// b::g::intersection might return a line with one point if the
|
||||||
|
// original line was very short and coords were dupes
|
||||||
|
if (!clipped_line.empty() && clipped_line[0].size() == 2)
|
||||||
|
{
|
||||||
|
if (clipped_line[0].size() == 2)
|
||||||
|
{
|
||||||
|
for (const auto &p : clipped_line[0])
|
||||||
|
{
|
||||||
|
tile_line.emplace_back(p.get<0>(), p.get<1>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tile_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::string &pbf_buffer)
|
Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::string &pbf_buffer)
|
||||||
{
|
{
|
||||||
|
using namespace util::coordinate_calculation;
|
||||||
// Vector tiles are 4096 virtual pixels on each side
|
|
||||||
const double tile_extent = 4096.0;
|
|
||||||
double min_lon, min_lat, max_lon, max_lat;
|
double min_lon, min_lat, max_lon, max_lat;
|
||||||
|
|
||||||
// Convert the z,x,y mercator tile coordinates into WSG84 lon/lat values
|
// Convert the z,x,y mercator tile coordinates into WSG84 lon/lat values
|
||||||
xyz2wsg84(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon, max_lat);
|
mercator::xyzToWSG84(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon,
|
||||||
|
max_lat);
|
||||||
|
|
||||||
util::Coordinate southwest{util::FloatLongitude(min_lon), util::FloatLatitude(min_lat)};
|
util::Coordinate southwest{util::FloatLongitude(min_lon), util::FloatLatitude(min_lat)};
|
||||||
util::Coordinate northeast{util::FloatLongitude(max_lon), util::FloatLatitude(max_lat)};
|
util::Coordinate northeast{util::FloatLongitude(max_lon), util::FloatLatitude(max_lat)};
|
||||||
@@ -185,13 +182,70 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
// This hits the OSRM StaticRTree
|
// This hits the OSRM StaticRTree
|
||||||
const auto edges = facade.GetEdgesInBox(southwest, northeast);
|
const auto edges = facade.GetEdgesInBox(southwest, northeast);
|
||||||
|
|
||||||
|
std::vector<int> used_weights;
|
||||||
|
std::unordered_map<int, std::size_t> weight_offsets;
|
||||||
|
uint8_t max_datasource_id = 0;
|
||||||
|
|
||||||
|
// Loop over all edges once to tally up all the attributes we'll need.
|
||||||
|
// We need to do this so that we know the attribute offsets to use
|
||||||
|
// when we encode each feature in the tile.
|
||||||
|
for (const auto &edge : edges)
|
||||||
|
{
|
||||||
|
int forward_weight = 0, reverse_weight = 0;
|
||||||
|
uint8_t forward_datasource = 0;
|
||||||
|
uint8_t reverse_datasource = 0;
|
||||||
|
|
||||||
|
if (edge.forward_packed_geometry_id != SPECIAL_EDGEID)
|
||||||
|
{
|
||||||
|
std::vector<EdgeWeight> forward_weight_vector;
|
||||||
|
facade.GetUncompressedWeights(edge.forward_packed_geometry_id, forward_weight_vector);
|
||||||
|
forward_weight = forward_weight_vector[edge.fwd_segment_position];
|
||||||
|
|
||||||
|
std::vector<uint8_t> forward_datasource_vector;
|
||||||
|
facade.GetUncompressedDatasources(edge.forward_packed_geometry_id,
|
||||||
|
forward_datasource_vector);
|
||||||
|
forward_datasource = forward_datasource_vector[edge.fwd_segment_position];
|
||||||
|
|
||||||
|
if (weight_offsets.find(forward_weight) == weight_offsets.end())
|
||||||
|
{
|
||||||
|
used_weights.push_back(forward_weight);
|
||||||
|
weight_offsets[forward_weight] = used_weights.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.reverse_packed_geometry_id != SPECIAL_EDGEID)
|
||||||
|
{
|
||||||
|
std::vector<EdgeWeight> reverse_weight_vector;
|
||||||
|
facade.GetUncompressedWeights(edge.reverse_packed_geometry_id, reverse_weight_vector);
|
||||||
|
|
||||||
|
BOOST_ASSERT(edge.fwd_segment_position < reverse_weight_vector.size());
|
||||||
|
|
||||||
|
reverse_weight =
|
||||||
|
reverse_weight_vector[reverse_weight_vector.size() - edge.fwd_segment_position - 1];
|
||||||
|
|
||||||
|
if (weight_offsets.find(reverse_weight) == weight_offsets.end())
|
||||||
|
{
|
||||||
|
used_weights.push_back(reverse_weight);
|
||||||
|
weight_offsets[reverse_weight] = used_weights.size() - 1;
|
||||||
|
}
|
||||||
|
std::vector<uint8_t> reverse_datasource_vector;
|
||||||
|
facade.GetUncompressedDatasources(edge.reverse_packed_geometry_id,
|
||||||
|
reverse_datasource_vector);
|
||||||
|
reverse_datasource = reverse_datasource_vector[reverse_datasource_vector.size() -
|
||||||
|
edge.fwd_segment_position - 1];
|
||||||
|
}
|
||||||
|
// Keep track of the highest datasource seen so that we don't write unnecessary
|
||||||
|
// data to the layer attribute values
|
||||||
|
max_datasource_id = std::max(max_datasource_id, forward_datasource);
|
||||||
|
max_datasource_id = std::max(max_datasource_id, reverse_datasource);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: extract speed values for compressed and uncompressed geometries
|
// TODO: extract speed values for compressed and uncompressed geometries
|
||||||
|
|
||||||
// Convert tile coordinates into mercator coordinates
|
// Convert tile coordinates into mercator coordinates
|
||||||
xyz2mercator(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon, max_lat);
|
mercator::xyzToMercator(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon,
|
||||||
const bbox tile_bbox{min_lon, min_lat, max_lon, max_lat};
|
max_lat);
|
||||||
|
const detail::BBox tile_bbox{min_lon, min_lat, max_lon, max_lat};
|
||||||
uint8_t max_datasource_id = 0;
|
|
||||||
|
|
||||||
// Protobuf serialized blocks when objects go out of scope, hence
|
// Protobuf serialized blocks when objects go out of scope, hence
|
||||||
// the extra scoping below.
|
// the extra scoping below.
|
||||||
@@ -263,38 +317,11 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
max_datasource_id = std::max(max_datasource_id, forward_datasource);
|
max_datasource_id = std::max(max_datasource_id, forward_datasource);
|
||||||
max_datasource_id = std::max(max_datasource_id, reverse_datasource);
|
max_datasource_id = std::max(max_datasource_id, reverse_datasource);
|
||||||
|
|
||||||
// If this is a valid forward edge, go ahead and add it to the tile
|
const auto encode_tile_line = [&layer_writer, &edge, &id, &max_datasource_id](
|
||||||
if (forward_weight != 0 && edge.forward_edge_based_node_id != SPECIAL_NODEID)
|
const detail::FixedLine &tile_line, const std::uint32_t speed_kmh,
|
||||||
|
const std::size_t duration, const std::uint8_t datasource,
|
||||||
|
std::int32_t &start_x, std::int32_t &start_y)
|
||||||
{
|
{
|
||||||
std::int32_t start_x = 0;
|
|
||||||
std::int32_t start_y = 0;
|
|
||||||
|
|
||||||
line_typed geo_line;
|
|
||||||
geo_line.emplace_back(static_cast<double>(util::toFloating(a.lon)),
|
|
||||||
static_cast<double>(util::toFloating(a.lat)));
|
|
||||||
geo_line.emplace_back(static_cast<double>(util::toFloating(b.lon)),
|
|
||||||
static_cast<double>(util::toFloating(b.lat)));
|
|
||||||
|
|
||||||
// Calculate the speed for this line
|
|
||||||
std::uint32_t speed =
|
|
||||||
static_cast<std::uint32_t>(round(length / forward_weight * 10 * 3.6));
|
|
||||||
|
|
||||||
line_type tile_line;
|
|
||||||
for (auto const &pt : geo_line)
|
|
||||||
{
|
|
||||||
double px_merc = pt.x;
|
|
||||||
double py_merc = pt.y;
|
|
||||||
lonlat2merc(px_merc, py_merc);
|
|
||||||
// convert lon/lat to tile coordinates
|
|
||||||
const auto px = std::round(
|
|
||||||
((px_merc - tile_bbox.minx) * tile_extent / 16.0 / tile_bbox.width()) *
|
|
||||||
tile_extent / 256.0);
|
|
||||||
const auto py = std::round(
|
|
||||||
((tile_bbox.maxy - py_merc) * tile_extent / 16.0 / tile_bbox.height()) *
|
|
||||||
tile_extent / 256.0);
|
|
||||||
tile_line.emplace_back(px, py);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here, we save the two attributes for our feature: the speed and the
|
// Here, we save the two attributes for our feature: the speed and the
|
||||||
// is_small
|
// is_small
|
||||||
// boolean. We onl serve up speeds from 0-139, so all we do is save the
|
// boolean. We onl serve up speeds from 0-139, so all we do is save the
|
||||||
@@ -316,17 +343,39 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
|
|
||||||
field.add_element(0); // "speed" tag key offset
|
field.add_element(0); // "speed" tag key offset
|
||||||
field.add_element(
|
field.add_element(
|
||||||
std::min(speed, 127u)); // save the speed value, capped at 127
|
std::min(speed_kmh, 127u)); // save the speed value, capped at 127
|
||||||
field.add_element(1); // "is_small" tag key offset
|
field.add_element(1); // "is_small" tag key offset
|
||||||
field.add_element(128 +
|
field.add_element(128 +
|
||||||
(edge.component.is_tiny ? 0 : 1)); // is_small feature
|
(edge.component.is_tiny ? 0 : 1)); // is_small feature
|
||||||
field.add_element(2); // "datasource" tag key offset
|
field.add_element(2); // "datasource" tag key offset
|
||||||
field.add_element(130 + forward_datasource); // datasource value offset
|
field.add_element(130 + datasource); // datasource value offset
|
||||||
|
field.add_element(3); // "duration" tag key offset
|
||||||
|
field.add_element(130 + max_datasource_id + 1 +
|
||||||
|
duration); // duration value offset
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
||||||
// Encode the geometry for the feature
|
// Encode the geometry for the feature
|
||||||
protozero::packed_field_uint32 geometry(feature_writer, 4);
|
protozero::packed_field_uint32 geometry(feature_writer, 4);
|
||||||
encode_linestring(tile_line, geometry, start_x, start_y);
|
encodeLinestring(tile_line, geometry, start_x, start_y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this is a valid forward edge, go ahead and add it to the tile
|
||||||
|
if (forward_weight != 0 && edge.forward_edge_based_node_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
std::int32_t start_x = 0;
|
||||||
|
std::int32_t start_y = 0;
|
||||||
|
|
||||||
|
// Calculate the speed for this line
|
||||||
|
std::uint32_t speed_kmh =
|
||||||
|
static_cast<std::uint32_t>(round(length / forward_weight * 10 * 3.6));
|
||||||
|
|
||||||
|
auto tile_line = coordinatesToTileLine(a, b, tile_bbox);
|
||||||
|
if (!tile_line.empty())
|
||||||
|
{
|
||||||
|
encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight],
|
||||||
|
forward_datasource, start_x, start_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,48 +386,15 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
std::int32_t start_x = 0;
|
std::int32_t start_x = 0;
|
||||||
std::int32_t start_y = 0;
|
std::int32_t start_y = 0;
|
||||||
|
|
||||||
line_typed geo_line;
|
// Calculate the speed for this line
|
||||||
geo_line.emplace_back(static_cast<double>(util::toFloating(b.lon)),
|
std::uint32_t speed_kmh =
|
||||||
static_cast<double>(util::toFloating(b.lat)));
|
static_cast<std::uint32_t>(round(length / reverse_weight * 10 * 3.6));
|
||||||
geo_line.emplace_back(static_cast<double>(util::toFloating(a.lon)),
|
|
||||||
static_cast<double>(util::toFloating(a.lat)));
|
|
||||||
|
|
||||||
const auto speed =
|
auto tile_line = coordinatesToTileLine(b, a, tile_bbox);
|
||||||
static_cast<const std::uint32_t>(round(length / reverse_weight * 10 * 3.6));
|
if (!tile_line.empty())
|
||||||
|
|
||||||
line_type tile_line;
|
|
||||||
for (auto const &pt : geo_line)
|
|
||||||
{
|
{
|
||||||
double px_merc = pt.x;
|
encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight],
|
||||||
double py_merc = pt.y;
|
reverse_datasource, start_x, start_y);
|
||||||
lonlat2merc(px_merc, py_merc);
|
|
||||||
// convert to integer tile coordinat
|
|
||||||
const auto px = std::round(
|
|
||||||
((px_merc - tile_bbox.minx) * tile_extent / 16.0 / tile_bbox.width()) *
|
|
||||||
tile_extent / 256.0);
|
|
||||||
const auto py = std::round(
|
|
||||||
((tile_bbox.maxy - py_merc) * tile_extent / 16.0 / tile_bbox.height()) *
|
|
||||||
tile_extent / 256.0);
|
|
||||||
tile_line.emplace_back(px, py);
|
|
||||||
}
|
|
||||||
|
|
||||||
protozero::pbf_writer feature_writer(layer_writer, 2);
|
|
||||||
feature_writer.add_enum(3, 2); // geometry type
|
|
||||||
feature_writer.add_uint64(1, id++); // id
|
|
||||||
{
|
|
||||||
protozero::packed_field_uint32 field(feature_writer, 2);
|
|
||||||
field.add_element(0); // "speed" tag key offset
|
|
||||||
field.add_element(
|
|
||||||
std::min(speed, 127u)); // save the speed value, capped at 127
|
|
||||||
field.add_element(1); // "is_small" tag key offset
|
|
||||||
field.add_element(128 +
|
|
||||||
(edge.component.is_tiny ? 0 : 1)); // is_small feature
|
|
||||||
field.add_element(2); // "datasource" tag key offset
|
|
||||||
field.add_element(130 + reverse_datasource); // datasource value offset
|
|
||||||
}
|
|
||||||
{
|
|
||||||
protozero::packed_field_uint32 geometry(feature_writer, 4);
|
|
||||||
encode_linestring(tile_line, geometry, start_x, start_y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,18 +406,17 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
layer_writer.add_string(3, "speed");
|
layer_writer.add_string(3, "speed");
|
||||||
layer_writer.add_string(3, "is_small");
|
layer_writer.add_string(3, "is_small");
|
||||||
layer_writer.add_string(3, "datasource");
|
layer_writer.add_string(3, "datasource");
|
||||||
|
layer_writer.add_string(3, "duration");
|
||||||
|
|
||||||
// Now, we write out the possible speed value arrays and possible is_tiny
|
// Now, we write out the possible speed value arrays and possible is_tiny
|
||||||
// values. Field type 4 is the "values" field. It's a variable type field,
|
// values. Field type 4 is the "values" field. It's a variable type field,
|
||||||
// so requires a two-step write (create the field, then write its value)
|
// so requires a two-step write (create the field, then write its value)
|
||||||
for (std::size_t i = 0; i < 128; i++)
|
for (std::size_t i = 0; i < 128; i++)
|
||||||
{
|
{
|
||||||
{
|
// Writing field type 4 == variant type
|
||||||
// Writing field type 4 == variant type
|
protozero::pbf_writer values_writer(layer_writer, 4);
|
||||||
protozero::pbf_writer values_writer(layer_writer, 4);
|
// Attribute value 5 == uin64 type
|
||||||
// Attribute value 5 == uin64 type
|
values_writer.add_uint64(5, i);
|
||||||
values_writer.add_uint64(5, i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
protozero::pbf_writer values_writer(layer_writer, 4);
|
protozero::pbf_writer values_writer(layer_writer, 4);
|
||||||
@@ -415,12 +430,19 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str
|
|||||||
}
|
}
|
||||||
for (std::size_t i = 0; i <= max_datasource_id; i++)
|
for (std::size_t i = 0; i <= max_datasource_id; i++)
|
||||||
{
|
{
|
||||||
{
|
// Writing field type 4 == variant type
|
||||||
// Writing field type 4 == variant type
|
protozero::pbf_writer values_writer(layer_writer, 4);
|
||||||
protozero::pbf_writer values_writer(layer_writer, 4);
|
// Attribute value 1 == string type
|
||||||
// Attribute value 1 == string type
|
values_writer.add_string(1, facade.GetDatasourceName(i));
|
||||||
values_writer.add_string(1, facade.GetDatasourceName(i));
|
}
|
||||||
}
|
for (auto weight : used_weights)
|
||||||
|
{
|
||||||
|
// Writing field type 4 == variant type
|
||||||
|
protozero::pbf_writer values_writer(layer_writer, 4);
|
||||||
|
// Attribute value 2 == float type
|
||||||
|
// Durations come out of OSRM in integer deciseconds, so we convert them
|
||||||
|
// to seconds with a simple /10 for display
|
||||||
|
values_writer.add_double(3, weight / 10.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,19 +135,7 @@ InternalRouteResult TripPlugin::ComputeRoute(const std::vector<PhantomNode> &sna
|
|||||||
}
|
}
|
||||||
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size());
|
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size());
|
||||||
|
|
||||||
std::vector<boost::optional<bool>> uturns;
|
shortest_path(min_route.segment_end_coordinates, parameters.uturns, min_route);
|
||||||
if (parameters.uturns.size() > 0)
|
|
||||||
{
|
|
||||||
uturns.resize(trip.size() + 1);
|
|
||||||
std::transform(trip.begin(), trip.end(), uturns.begin(), [¶meters](const NodeID idx)
|
|
||||||
{
|
|
||||||
return parameters.uturns[idx];
|
|
||||||
});
|
|
||||||
BOOST_ASSERT(uturns.size() > 0);
|
|
||||||
uturns.back() = parameters.uturns[trip.front()];
|
|
||||||
}
|
|
||||||
|
|
||||||
shortest_path(min_route.segment_end_coordinates, uturns, min_route);
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
|
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
|
||||||
return min_route;
|
return min_route;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "engine/plugins/viaroute.hpp"
|
#include "engine/plugins/viaroute.hpp"
|
||||||
#include "engine/datafacade/datafacade_base.hpp"
|
#include "engine/datafacade/datafacade_base.hpp"
|
||||||
#include "engine/api/route_api.hpp"
|
#include "engine/api/route_api.hpp"
|
||||||
#include "engine/object_encoder.hpp"
|
|
||||||
#include "engine/status.hpp"
|
#include "engine/status.hpp"
|
||||||
|
|
||||||
#include "util/for_each_pair.hpp"
|
#include "util/for_each_pair.hpp"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "extractor/guidance/toolkit.hpp"
|
#include "extractor/guidance/toolkit.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -34,12 +35,13 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
SpeedProfileProperties speed_profile)
|
ProfileProperties profile_properties,
|
||||||
|
const util::NameTable &name_table)
|
||||||
: m_max_edge_id(0), m_node_info_list(node_info_list),
|
: m_max_edge_id(0), m_node_info_list(node_info_list),
|
||||||
m_node_based_graph(std::move(node_based_graph)),
|
m_node_based_graph(std::move(node_based_graph)),
|
||||||
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
|
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
|
||||||
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
|
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
|
||||||
speed_profile(std::move(speed_profile))
|
profile_properties(std::move(profile_properties)), name_table(name_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,10 +125,9 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
|
|||||||
// traverse arrays from start and end respectively
|
// traverse arrays from start and end respectively
|
||||||
for (const auto i : util::irange(0UL, geometry_size))
|
for (const auto i : util::irange(0UL, geometry_size))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT(current_edge_source_coordinate_id ==
|
||||||
current_edge_source_coordinate_id ==
|
m_compressed_edge_container.GetBucketReference(
|
||||||
m_compressed_edge_container.GetBucketReference(edge_id_2)[geometry_size - 1 - i]
|
edge_id_2)[geometry_size - 1 - i].node_id);
|
||||||
.node_id);
|
|
||||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id;
|
const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id;
|
||||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||||
|
|
||||||
@@ -207,7 +208,7 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
|
|||||||
// oneway streets always require this self-loop. Other streets only if a u-turn plus
|
// oneway streets always require this self-loop. Other streets only if a u-turn plus
|
||||||
// traversal
|
// traversal
|
||||||
// of the street takes longer than the loop
|
// of the street takes longer than the loop
|
||||||
m_edge_based_node_weights.push_back(edge_data.distance + speed_profile.u_turn_penalty);
|
m_edge_based_node_weights.push_back(edge_data.distance + profile_properties.u_turn_penalty);
|
||||||
|
|
||||||
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
||||||
edge_data.edge_id = numbered_edges_count;
|
edge_data.edge_id = numbered_edges_count;
|
||||||
@@ -276,6 +277,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
{
|
{
|
||||||
util::SimpleLogger().Write() << "generating edge-expanded edges";
|
util::SimpleLogger().Write() << "generating edge-expanded edges";
|
||||||
|
|
||||||
|
BOOST_ASSERT(lua_state != nullptr);
|
||||||
|
const bool use_turn_function = util::luaFunctionExists(lua_state, "turn_function");
|
||||||
|
|
||||||
std::size_t node_based_edge_counter = 0;
|
std::size_t node_based_edge_counter = 0;
|
||||||
std::size_t original_edges_counter = 0;
|
std::size_t original_edges_counter = 0;
|
||||||
restricted_turns_counter = 0;
|
restricted_turns_counter = 0;
|
||||||
@@ -292,8 +296,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
edge_penalty_file.open(edge_fixed_penalties_filename.c_str(), std::ios::binary);
|
edge_penalty_file.open(edge_fixed_penalties_filename.c_str(), std::ios::binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes a dummy value that is updated later
|
// Writes a dummy value at the front that is updated later with the total length
|
||||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
const unsigned length_prefix_empty_space{0};
|
||||||
|
edge_data_file.write(reinterpret_cast<const char *>(&length_prefix_empty_space),
|
||||||
|
sizeof(length_prefix_empty_space));
|
||||||
|
|
||||||
std::vector<OriginalEdgeData> original_edge_data_vector;
|
std::vector<OriginalEdgeData> original_edge_data_vector;
|
||||||
original_edge_data_vector.reserve(1024 * 1024);
|
original_edge_data_vector.reserve(1024 * 1024);
|
||||||
@@ -302,8 +308,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
// linear number of turns only.
|
// linear number of turns only.
|
||||||
util::Percent progress(m_node_based_graph->GetNumberOfNodes());
|
util::Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
guidance::TurnAnalysis turn_analysis( *m_node_based_graph, m_node_info_list,
|
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
|
||||||
*m_restriction_map, m_barrier_nodes, m_compressed_edge_container );
|
m_barrier_nodes, m_compressed_edge_container, name_table);
|
||||||
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
// progress.printStatus(node_u);
|
// progress.printStatus(node_u);
|
||||||
@@ -315,15 +321,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
}
|
}
|
||||||
|
|
||||||
++node_based_edge_counter;
|
++node_based_edge_counter;
|
||||||
auto turn_candidates = turn_analysis.getTurns(node_u, edge_from_u);
|
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);
|
||||||
|
|
||||||
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
|
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
|
||||||
|
|
||||||
for (const auto turn : turn_candidates)
|
for (const auto turn : possible_turns)
|
||||||
{
|
{
|
||||||
if (!turn.valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const double turn_angle = turn.angle;
|
const double turn_angle = turn.angle;
|
||||||
|
|
||||||
// only add an edge if turn is not prohibited
|
// only add an edge if turn is not prohibited
|
||||||
@@ -338,15 +341,15 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
unsigned distance = edge_data1.distance;
|
unsigned distance = edge_data1.distance;
|
||||||
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
||||||
{
|
{
|
||||||
distance += speed_profile.traffic_signal_penalty;
|
distance += profile_properties.traffic_signal_penalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
const int turn_penalty = use_turn_function ? GetTurnPenalty(turn_angle, lua_state) : 0;
|
||||||
const auto turn_instruction = turn.instruction;
|
const auto turn_instruction = turn.instruction;
|
||||||
|
|
||||||
if (guidance::isUturn(turn_instruction))
|
if (guidance::isUturn(turn_instruction))
|
||||||
{
|
{
|
||||||
distance += speed_profile.u_turn_penalty;
|
distance += profile_properties.u_turn_penalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
distance += turn_penalty;
|
distance += turn_penalty;
|
||||||
@@ -422,8 +425,13 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
|
|
||||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
|
|
||||||
|
// Finally jump back to the empty space at the beginning and write length prefix
|
||||||
edge_data_file.seekp(std::ios::beg);
|
edge_data_file.seekp(std::ios::beg);
|
||||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
|
||||||
|
const auto length_prefix = boost::numeric_cast<unsigned>(original_edges_counter);
|
||||||
|
static_assert(sizeof(length_prefix_empty_space) == sizeof(length_prefix), "type mismatch");
|
||||||
|
|
||||||
|
edge_data_file.write(reinterpret_cast<const char *>(&length_prefix), sizeof(length_prefix));
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
|
util::SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
|
||||||
<< " edge based nodes";
|
<< " edge based nodes";
|
||||||
@@ -441,20 +449,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
|
|
||||||
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(lua_state != nullptr);
|
||||||
if (speed_profile.has_turn_penalty_function)
|
try
|
||||||
{
|
{
|
||||||
try
|
// call lua profile to compute turn penalty
|
||||||
{
|
double penalty = luabind::call_function<double>(lua_state, "turn_function", 180. - angle);
|
||||||
// call lua profile to compute turn penalty
|
return boost::numeric_cast<int>(penalty);
|
||||||
double penalty =
|
}
|
||||||
luabind::call_function<double>(lua_state, "turn_function", 180. - angle);
|
catch (const luabind::error &er)
|
||||||
return static_cast<int>(penalty);
|
{
|
||||||
}
|
util::SimpleLogger().Write(logWARNING) << er.what();
|
||||||
catch (const luabind::error &er)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logWARNING) << er.what();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,6 +288,8 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
|
|||||||
const auto all_edges_list_end_ = all_edges_list.end();
|
const auto all_edges_list_end_ = all_edges_list.end();
|
||||||
const auto all_nodes_list_end_ = all_nodes_list.end();
|
const auto all_nodes_list_end_ = all_nodes_list.end();
|
||||||
|
|
||||||
|
const auto has_segment_function = util::luaFunctionExists(segment_state, "segment_function");
|
||||||
|
|
||||||
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
|
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
|
||||||
{
|
{
|
||||||
// skip all invalid edges
|
// skip all invalid edges
|
||||||
@@ -323,7 +325,7 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
|
|||||||
edge_iterator->source_coordinate,
|
edge_iterator->source_coordinate,
|
||||||
util::Coordinate(node_iterator->lon, node_iterator->lat));
|
util::Coordinate(node_iterator->lon, node_iterator->lat));
|
||||||
|
|
||||||
if (util::lua_function_exists(segment_state, "segment_function"))
|
if (has_segment_function)
|
||||||
{
|
{
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
segment_state, "segment_function", boost::cref(edge_iterator->source_coordinate),
|
segment_state, "segment_function", boost::cref(edge_iterator->source_coordinate),
|
||||||
|
|||||||
+35
-66
@@ -15,6 +15,7 @@
|
|||||||
#include "util/timing_util.hpp"
|
#include "util/timing_util.hpp"
|
||||||
#include "util/lua_util.hpp"
|
#include "util/lua_util.hpp"
|
||||||
#include "util/graph_loader.hpp"
|
#include "util/graph_loader.hpp"
|
||||||
|
#include "util/name_table.hpp"
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -74,6 +76,9 @@ namespace extractor
|
|||||||
*/
|
*/
|
||||||
int Extractor::run()
|
int Extractor::run()
|
||||||
{
|
{
|
||||||
|
// setup scripting environment
|
||||||
|
ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
util::LogPolicy::GetInstance().Unmute();
|
util::LogPolicy::GetInstance().Unmute();
|
||||||
@@ -88,9 +93,6 @@ int Extractor::run()
|
|||||||
util::SimpleLogger().Write() << "Profile: " << config.profile_path.filename().string();
|
util::SimpleLogger().Write() << "Profile: " << config.profile_path.filename().string();
|
||||||
util::SimpleLogger().Write() << "Threads: " << number_of_threads;
|
util::SimpleLogger().Write() << "Threads: " << number_of_threads;
|
||||||
|
|
||||||
// setup scripting environment
|
|
||||||
ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
|
|
||||||
|
|
||||||
ExtractionContainers extraction_containers;
|
ExtractionContainers extraction_containers;
|
||||||
auto extractor_callbacks = util::make_unique<ExtractorCallbacks>(extraction_containers);
|
auto extractor_callbacks = util::make_unique<ExtractorCallbacks>(extraction_containers);
|
||||||
|
|
||||||
@@ -106,15 +108,12 @@ int Extractor::run()
|
|||||||
util::SimpleLogger().Write() << "Parsing in progress..";
|
util::SimpleLogger().Write() << "Parsing in progress..";
|
||||||
TIMER_START(parsing);
|
TIMER_START(parsing);
|
||||||
|
|
||||||
lua_State *segment_state = scripting_environment.GetLuaState();
|
auto& main_context = scripting_environment.GetContex();
|
||||||
|
|
||||||
if (util::lua_function_exists(segment_state, "source_function"))
|
// setup raster sources
|
||||||
|
if (util::luaFunctionExists(main_context.state, "source_function"))
|
||||||
{
|
{
|
||||||
// bind a single instance of SourceContainer class to relevant lua state
|
luabind::call_function<void>(main_context.state, "source_function");
|
||||||
SourceContainer sources;
|
|
||||||
luabind::globals(segment_state)["sources"] = sources;
|
|
||||||
|
|
||||||
luabind::call_function<void>(segment_state, "source_function");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string generator = header.get("generator");
|
std::string generator = header.get("generator");
|
||||||
@@ -141,7 +140,7 @@ int Extractor::run()
|
|||||||
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
|
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
|
||||||
|
|
||||||
// setup restriction parser
|
// setup restriction parser
|
||||||
const RestrictionParser restriction_parser(scripting_environment.GetLuaState());
|
const RestrictionParser restriction_parser(main_context.state, main_context.properties);
|
||||||
|
|
||||||
while (const osmium::memory::Buffer buffer = reader.read())
|
while (const osmium::memory::Buffer buffer = reader.read())
|
||||||
{
|
{
|
||||||
@@ -164,7 +163,7 @@ int Extractor::run()
|
|||||||
{
|
{
|
||||||
ExtractionNode result_node;
|
ExtractionNode result_node;
|
||||||
ExtractionWay result_way;
|
ExtractionWay result_way;
|
||||||
lua_State *local_state = scripting_environment.GetLuaState();
|
auto& local_context = scripting_environment.GetContex();
|
||||||
|
|
||||||
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
||||||
{
|
{
|
||||||
@@ -176,7 +175,7 @@ int Extractor::run()
|
|||||||
result_node.clear();
|
result_node.clear();
|
||||||
++number_of_nodes;
|
++number_of_nodes;
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
local_state, "node_function",
|
local_context.state, "node_function",
|
||||||
boost::cref(static_cast<const osmium::Node &>(*entity)),
|
boost::cref(static_cast<const osmium::Node &>(*entity)),
|
||||||
boost::ref(result_node));
|
boost::ref(result_node));
|
||||||
resulting_nodes.push_back(std::make_pair(x, result_node));
|
resulting_nodes.push_back(std::make_pair(x, result_node));
|
||||||
@@ -185,7 +184,7 @@ int Extractor::run()
|
|||||||
result_way.clear();
|
result_way.clear();
|
||||||
++number_of_ways;
|
++number_of_ways;
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
local_state, "way_function",
|
local_context.state, "way_function",
|
||||||
boost::cref(static_cast<const osmium::Way &>(*entity)),
|
boost::cref(static_cast<const osmium::Way &>(*entity)),
|
||||||
boost::ref(result_way));
|
boost::ref(result_way));
|
||||||
resulting_ways.push_back(std::make_pair(x, result_way));
|
resulting_ways.push_back(std::make_pair(x, result_way));
|
||||||
@@ -237,26 +236,29 @@ int Extractor::run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
extraction_containers.PrepareData(config.output_file_name, config.restriction_file_name,
|
extraction_containers.PrepareData(config.output_file_name, config.restriction_file_name,
|
||||||
config.names_file_name, segment_state);
|
config.names_file_name, main_context.state);
|
||||||
|
|
||||||
|
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
|
||||||
|
|
||||||
TIMER_STOP(extracting);
|
TIMER_STOP(extracting);
|
||||||
util::SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting)
|
util::SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting)
|
||||||
<< "s";
|
<< "s";
|
||||||
}
|
}
|
||||||
|
// we do this for scoping
|
||||||
|
// TODO move to own functions
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logWARNING) << e.what();
|
util::SimpleLogger().Write(logWARNING) << e.what();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Transform the node-based graph that OSM is based on into an edge-based graph
|
// Transform the node-based graph that OSM is based on into an edge-based graph
|
||||||
// that is better for routing. Every edge becomes a node, and every valid
|
// that is better for routing. Every edge becomes a node, and every valid
|
||||||
// movement (e.g. turn from A->B, and B->A) becomes an edge
|
// movement (e.g. turn from A->B, and B->A) becomes an edge
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// // Create a new lua state
|
auto& main_context = scripting_environment.GetContex();
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
util::SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
||||||
|
|
||||||
@@ -267,7 +269,9 @@ int Extractor::run()
|
|||||||
std::vector<bool> node_is_startpoint;
|
std::vector<bool> node_is_startpoint;
|
||||||
std::vector<EdgeWeight> edge_based_node_weights;
|
std::vector<EdgeWeight> edge_based_node_weights;
|
||||||
std::vector<QueryNode> internal_to_external_node_map;
|
std::vector<QueryNode> internal_to_external_node_map;
|
||||||
auto graph_size = BuildEdgeExpandedGraph(internal_to_external_node_map,
|
auto graph_size = BuildEdgeExpandedGraph(main_context.state,
|
||||||
|
main_context.properties,
|
||||||
|
internal_to_external_node_map,
|
||||||
edge_based_node_list, node_is_startpoint,
|
edge_based_node_list, node_is_startpoint,
|
||||||
edge_based_node_weights, edge_based_edge_list);
|
edge_based_node_weights, edge_based_edge_list);
|
||||||
|
|
||||||
@@ -313,46 +317,15 @@ int Extractor::run()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Extractor::WriteProfileProperties(const std::string& output_path, const ProfileProperties& properties) const
|
||||||
\brief Setups scripting environment (lua-scripting)
|
|
||||||
Also initializes speed profile.
|
|
||||||
*/
|
|
||||||
void Extractor::SetupScriptingEnvironment(lua_State *lua_state,
|
|
||||||
SpeedProfileProperties &speed_profile)
|
|
||||||
{
|
{
|
||||||
// open utility libraries string library;
|
boost::filesystem::ofstream out_stream(output_path);
|
||||||
luaL_openlibs(lua_state);
|
if (!out_stream)
|
||||||
|
|
||||||
// adjust lua load path
|
|
||||||
util::luaAddScriptFolderToLoadPath(lua_state, config.profile_path.string().c_str());
|
|
||||||
|
|
||||||
// Now call our function in a lua script
|
|
||||||
if (0 != luaL_dofile(lua_state, config.profile_path.string().c_str()))
|
|
||||||
{
|
{
|
||||||
std::stringstream msg;
|
throw util::exception("Could not open " + output_path + " for writing.");
|
||||||
msg << lua_tostring(lua_state, -1) << " occurred in scripting block";
|
|
||||||
throw util::exception(msg.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
|
out_stream.write(reinterpret_cast<const char*>(&properties), sizeof(properties));
|
||||||
{
|
|
||||||
std::stringstream msg;
|
|
||||||
msg << lua_tostring(lua_state, -1) << " occurred in scripting block";
|
|
||||||
throw util::exception(msg.str());
|
|
||||||
}
|
|
||||||
speed_profile.traffic_signal_penalty = 10 * lua_tointeger(lua_state, -1);
|
|
||||||
util::SimpleLogger().Write(logDEBUG) << "traffic_signal_penalty: "
|
|
||||||
<< speed_profile.traffic_signal_penalty;
|
|
||||||
|
|
||||||
if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
|
|
||||||
{
|
|
||||||
std::stringstream msg;
|
|
||||||
msg << lua_tostring(lua_state, -1) << " occurred in scripting block";
|
|
||||||
throw util::exception(msg.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
speed_profile.u_turn_penalty = 10 * lua_tointeger(lua_state, -1);
|
|
||||||
speed_profile.has_turn_penalty_function = util::lua_function_exists(lua_state, "turn_function");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extractor::FindComponents(unsigned max_edge_id,
|
void Extractor::FindComponents(unsigned max_edge_id,
|
||||||
@@ -495,18 +468,14 @@ Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
\brief Building an edge-expanded graph from node-based input and turn restrictions
|
\brief Building an edge-expanded graph from node-based input and turn restrictions
|
||||||
*/
|
*/
|
||||||
std::pair<std::size_t, std::size_t>
|
std::pair<std::size_t, std::size_t>
|
||||||
Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
|
Extractor::BuildEdgeExpandedGraph(lua_State* lua_state,
|
||||||
|
const ProfileProperties& profile_properties,
|
||||||
|
std::vector<QueryNode> &internal_to_external_node_map,
|
||||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
|
||||||
{
|
{
|
||||||
lua_State *lua_state = luaL_newstate();
|
|
||||||
luabind::open(lua_state);
|
|
||||||
|
|
||||||
SpeedProfileProperties speed_profile;
|
|
||||||
SetupScriptingEnvironment(lua_state, speed_profile);
|
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
std::unordered_set<NodeID> traffic_lights;
|
||||||
|
|
||||||
@@ -515,23 +484,23 @@ Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_n
|
|||||||
LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map);
|
LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map);
|
||||||
|
|
||||||
CompressedEdgeContainer compressed_edge_container;
|
CompressedEdgeContainer compressed_edge_container;
|
||||||
GraphCompressor graph_compressor(speed_profile);
|
GraphCompressor graph_compressor;
|
||||||
graph_compressor.Compress(barrier_nodes, traffic_lights, *restriction_map, *node_based_graph,
|
graph_compressor.Compress(barrier_nodes, traffic_lights, *restriction_map, *node_based_graph,
|
||||||
compressed_edge_container);
|
compressed_edge_container);
|
||||||
|
|
||||||
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
||||||
|
|
||||||
|
util::NameTable name_table(config.names_file_name);
|
||||||
|
|
||||||
EdgeBasedGraphFactory edge_based_graph_factory(
|
EdgeBasedGraphFactory edge_based_graph_factory(
|
||||||
node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights,
|
node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights,
|
||||||
std::const_pointer_cast<RestrictionMap const>(restriction_map),
|
std::const_pointer_cast<RestrictionMap const>(restriction_map),
|
||||||
internal_to_external_node_map, speed_profile);
|
internal_to_external_node_map, profile_properties, name_table);
|
||||||
|
|
||||||
edge_based_graph_factory.Run(config.edge_output_path, lua_state,
|
edge_based_graph_factory.Run(config.edge_output_path, lua_state,
|
||||||
config.edge_segment_lookup_path, config.edge_penalty_path,
|
config.edge_segment_lookup_path, config.edge_penalty_path,
|
||||||
config.generate_edge_lookup);
|
config.generate_edge_lookup);
|
||||||
|
|
||||||
lua_close(lua_state);
|
|
||||||
|
|
||||||
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||||
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
|
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
|
||||||
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
GraphCompressor::GraphCompressor(SpeedProfileProperties speed_profile)
|
|
||||||
: speed_profile(std::move(speed_profile))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
RestrictionMap &restriction_map,
|
RestrictionMap &restriction_map,
|
||||||
|
|||||||
+1473
-1209
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
#include "extractor/restriction_parser.hpp"
|
#include "extractor/restriction_parser.hpp"
|
||||||
#include "extractor/extraction_way.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
|
|
||||||
#include "extractor/external_memory_node.hpp"
|
#include "extractor/external_memory_node.hpp"
|
||||||
#include "util/lua_util.hpp"
|
#include "util/lua_util.hpp"
|
||||||
@@ -33,37 +33,18 @@ int luaErrorCallback(lua_State *lua_state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestrictionParser::RestrictionParser(lua_State *lua_state) : use_turn_restrictions(true)
|
RestrictionParser::RestrictionParser(lua_State *lua_state, const ProfileProperties &properties)
|
||||||
|
: use_turn_restrictions(properties.use_turn_restrictions)
|
||||||
{
|
{
|
||||||
ReadUseRestrictionsSetting(lua_state);
|
|
||||||
|
|
||||||
if (use_turn_restrictions)
|
if (use_turn_restrictions)
|
||||||
{
|
{
|
||||||
ReadRestrictionExceptions(lua_state);
|
ReadRestrictionExceptions(lua_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestrictionParser::ReadUseRestrictionsSetting(lua_State *lua_state)
|
|
||||||
{
|
|
||||||
if (0 == luaL_dostring(lua_state, "return use_turn_restrictions\n") &&
|
|
||||||
lua_isboolean(lua_state, -1))
|
|
||||||
{
|
|
||||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_turn_restrictions)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write() << "Using turn restrictions";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write() << "Ignoring turn restrictions";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state)
|
void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state)
|
||||||
{
|
{
|
||||||
if (util::lua_function_exists(lua_state, "get_exceptions"))
|
if (util::luaFunctionExists(lua_state, "get_exceptions"))
|
||||||
{
|
{
|
||||||
luabind::set_pcall_callback(&luaErrorCallback);
|
luabind::set_pcall_callback(&luaErrorCallback);
|
||||||
// get list of turn restriction exceptions
|
// get list of turn restriction exceptions
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
#include "extractor/internal_extractor_edge.hpp"
|
#include "extractor/internal_extractor_edge.hpp"
|
||||||
#include "extractor/external_memory_node.hpp"
|
#include "extractor/external_memory_node.hpp"
|
||||||
#include "extractor/raster_source.hpp"
|
#include "extractor/raster_source.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "util/lua_util.hpp"
|
#include "util/lua_util.hpp"
|
||||||
|
#include "util/make_unique.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/simple_logger.hpp"
|
#include "util/simple_logger.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
@@ -56,117 +58,126 @@ ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) : file_
|
|||||||
util::SimpleLogger().Write() << "Using script " << file_name;
|
util::SimpleLogger().Write() << "Using script " << file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingEnvironment::InitLuaState(lua_State *lua_state)
|
void ScriptingEnvironment::InitContext(ScriptingEnvironment::Context &context)
|
||||||
{
|
{
|
||||||
typedef double (osmium::Location::*location_member_ptr_type)() const;
|
typedef double (osmium::Location::*location_member_ptr_type)() const;
|
||||||
|
|
||||||
luabind::open(lua_state);
|
luabind::open(context.state);
|
||||||
// open utility libraries string library;
|
// open utility libraries string library;
|
||||||
luaL_openlibs(lua_state);
|
luaL_openlibs(context.state);
|
||||||
|
|
||||||
util::luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
|
util::luaAddScriptFolderToLoadPath(context.state, file_name.c_str());
|
||||||
|
|
||||||
// Add our function to the state's global scope
|
// Add our function to the state's global scope
|
||||||
luabind::module(
|
luabind::module(context.state)
|
||||||
lua_state)[luabind::def("print", util::LUA_print<std::string>),
|
[luabind::def("durationIsValid", durationIsValid),
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
luabind::def("parseDuration", parseDuration),
|
||||||
luabind::def("parseDuration", parseDuration),
|
luabind::class_<TravelMode>("mode")
|
||||||
luabind::class_<TravelMode>("mode")
|
.enum_("enums")[luabind::value("inaccessible", TRAVEL_MODE_INACCESSIBLE),
|
||||||
.enum_("enums")[luabind::value("inaccessible", TRAVEL_MODE_INACCESSIBLE),
|
luabind::value("driving", TRAVEL_MODE_DRIVING),
|
||||||
luabind::value("driving", TRAVEL_MODE_DRIVING),
|
luabind::value("cycling", TRAVEL_MODE_CYCLING),
|
||||||
luabind::value("cycling", TRAVEL_MODE_CYCLING),
|
luabind::value("walking", TRAVEL_MODE_WALKING),
|
||||||
luabind::value("walking", TRAVEL_MODE_WALKING),
|
luabind::value("ferry", TRAVEL_MODE_FERRY),
|
||||||
luabind::value("ferry", TRAVEL_MODE_FERRY),
|
luabind::value("train", TRAVEL_MODE_TRAIN),
|
||||||
luabind::value("train", TRAVEL_MODE_TRAIN),
|
luabind::value("pushing_bike", TRAVEL_MODE_PUSHING_BIKE),
|
||||||
luabind::value("pushing_bike", TRAVEL_MODE_PUSHING_BIKE),
|
luabind::value("movable_bridge", TRAVEL_MODE_MOVABLE_BRIDGE),
|
||||||
luabind::value("movable_bridge", TRAVEL_MODE_MOVABLE_BRIDGE),
|
luabind::value("steps_up", TRAVEL_MODE_STEPS_UP),
|
||||||
luabind::value("steps_up", TRAVEL_MODE_STEPS_UP),
|
luabind::value("steps_down", TRAVEL_MODE_STEPS_DOWN),
|
||||||
luabind::value("steps_down", TRAVEL_MODE_STEPS_DOWN),
|
luabind::value("river_up", TRAVEL_MODE_RIVER_UP),
|
||||||
luabind::value("river_up", TRAVEL_MODE_RIVER_UP),
|
luabind::value("river_down", TRAVEL_MODE_RIVER_DOWN),
|
||||||
luabind::value("river_down", TRAVEL_MODE_RIVER_DOWN),
|
luabind::value("route", TRAVEL_MODE_ROUTE)],
|
||||||
luabind::value("route", TRAVEL_MODE_ROUTE)],
|
luabind::class_<SourceContainer>("sources")
|
||||||
luabind::class_<SourceContainer>("sources")
|
.def(luabind::constructor<>())
|
||||||
.def(luabind::constructor<>())
|
.def("load", &SourceContainer::loadRasterSource)
|
||||||
.def("load", &SourceContainer::loadRasterSource)
|
.def("query", &SourceContainer::getRasterDataFromSource)
|
||||||
.def("query", &SourceContainer::getRasterDataFromSource)
|
.def("interpolate", &SourceContainer::getRasterInterpolateFromSource),
|
||||||
.def("interpolate", &SourceContainer::getRasterInterpolateFromSource),
|
luabind::class_<const float>("constants")
|
||||||
luabind::class_<const float>("constants")
|
.enum_("enums")[luabind::value("precision", COORDINATE_PRECISION)],
|
||||||
.enum_("enums")[luabind::value("precision", COORDINATE_PRECISION)],
|
|
||||||
|
|
||||||
luabind::class_<std::vector<std::string>>("vector").def(
|
luabind::class_<ProfileProperties>("ProfileProperties")
|
||||||
"Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
|
.def(luabind::constructor<>())
|
||||||
&std::vector<std::string>::push_back)),
|
.property("traffic_signal_penalty", &ProfileProperties::GetTrafficSignalPenalty,
|
||||||
|
&ProfileProperties::SetTrafficSignalPenalty)
|
||||||
|
.property("u_turn_penalty", &ProfileProperties::GetUturnPenalty,
|
||||||
|
&ProfileProperties::SetUturnPenalty)
|
||||||
|
.def_readwrite("allow_u_turn_at_via", &ProfileProperties::allow_u_turn_at_via),
|
||||||
|
|
||||||
luabind::class_<osmium::Location>("Location")
|
luabind::class_<std::vector<std::string>>("vector")
|
||||||
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
|
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
|
||||||
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
|
&std::vector<std::string>::push_back)),
|
||||||
|
|
||||||
luabind::class_<osmium::Node>("Node")
|
luabind::class_<osmium::Location>("Location")
|
||||||
// .def<node_member_ptr_type>("tags", &osmium::Node::tags)
|
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
|
||||||
.def("location", &osmium::Node::location)
|
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
|
||||||
.def("get_value_by_key", &osmium::Node::get_value_by_key)
|
|
||||||
.def("get_value_by_key", &get_value_by_key<osmium::Node>)
|
|
||||||
.def("id", &osmium::Node::id),
|
|
||||||
|
|
||||||
luabind::class_<ExtractionNode>("ResultNode")
|
luabind::class_<osmium::Node>("Node")
|
||||||
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
|
// .def<node_member_ptr_type>("tags", &osmium::Node::tags)
|
||||||
.def_readwrite("barrier", &ExtractionNode::barrier),
|
.def("location", &osmium::Node::location)
|
||||||
|
.def("get_value_by_key", &osmium::Node::get_value_by_key)
|
||||||
|
.def("get_value_by_key", &get_value_by_key<osmium::Node>)
|
||||||
|
.def("id", &osmium::Node::id),
|
||||||
|
|
||||||
luabind::class_<ExtractionWay>("ResultWay")
|
luabind::class_<ExtractionNode>("ResultNode")
|
||||||
// .def(luabind::constructor<>())
|
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
|
||||||
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
|
.def_readwrite("barrier", &ExtractionNode::barrier),
|
||||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
|
||||||
.def_readwrite("name", &ExtractionWay::name)
|
|
||||||
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
|
||||||
.def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted)
|
|
||||||
.def_readwrite("is_startpoint", &ExtractionWay::is_startpoint)
|
|
||||||
.def_readwrite("duration", &ExtractionWay::duration)
|
|
||||||
.property("forward_mode", &ExtractionWay::get_forward_mode,
|
|
||||||
&ExtractionWay::set_forward_mode)
|
|
||||||
.property("backward_mode", &ExtractionWay::get_backward_mode,
|
|
||||||
&ExtractionWay::set_backward_mode),
|
|
||||||
luabind::class_<osmium::Way>("Way")
|
|
||||||
.def("get_value_by_key", &osmium::Way::get_value_by_key)
|
|
||||||
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
|
|
||||||
.def("id", &osmium::Way::id),
|
|
||||||
luabind::class_<InternalExtractorEdge>("EdgeSource")
|
|
||||||
.def_readonly("source_coordinate", &InternalExtractorEdge::source_coordinate)
|
|
||||||
.def_readwrite("weight_data", &InternalExtractorEdge::weight_data),
|
|
||||||
luabind::class_<InternalExtractorEdge::WeightData>("WeightData")
|
|
||||||
.def_readwrite("speed", &InternalExtractorEdge::WeightData::speed),
|
|
||||||
luabind::class_<ExternalMemoryNode>("EdgeTarget")
|
|
||||||
.property("lon", &lonToDouble<ExternalMemoryNode>)
|
|
||||||
.property("lat", &latToDouble<ExternalMemoryNode>),
|
|
||||||
luabind::class_<util::Coordinate>("Coordinate")
|
|
||||||
.property("lon", &lonToDouble<util::Coordinate>)
|
|
||||||
.property("lat", &latToDouble<util::Coordinate>),
|
|
||||||
luabind::class_<RasterDatum>("RasterDatum")
|
|
||||||
.def_readonly("datum", &RasterDatum::datum)
|
|
||||||
.def("invalid_data", &RasterDatum::get_invalid)];
|
|
||||||
|
|
||||||
if (0 != luaL_dofile(lua_state, file_name.c_str()))
|
luabind::class_<ExtractionWay>("ResultWay")
|
||||||
|
// .def(luabind::constructor<>())
|
||||||
|
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
|
||||||
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
|
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
||||||
|
.def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted)
|
||||||
|
.def_readwrite("is_startpoint", &ExtractionWay::is_startpoint)
|
||||||
|
.def_readwrite("duration", &ExtractionWay::duration)
|
||||||
|
.property("forward_mode", &ExtractionWay::get_forward_mode,
|
||||||
|
&ExtractionWay::set_forward_mode)
|
||||||
|
.property("backward_mode", &ExtractionWay::get_backward_mode,
|
||||||
|
&ExtractionWay::set_backward_mode),
|
||||||
|
luabind::class_<osmium::Way>("Way")
|
||||||
|
.def("get_value_by_key", &osmium::Way::get_value_by_key)
|
||||||
|
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
|
||||||
|
.def("id", &osmium::Way::id),
|
||||||
|
luabind::class_<InternalExtractorEdge>("EdgeSource")
|
||||||
|
.def_readonly("source_coordinate", &InternalExtractorEdge::source_coordinate)
|
||||||
|
.def_readwrite("weight_data", &InternalExtractorEdge::weight_data),
|
||||||
|
luabind::class_<InternalExtractorEdge::WeightData>("WeightData")
|
||||||
|
.def_readwrite("speed", &InternalExtractorEdge::WeightData::speed),
|
||||||
|
luabind::class_<ExternalMemoryNode>("EdgeTarget")
|
||||||
|
.property("lon", &lonToDouble<ExternalMemoryNode>)
|
||||||
|
.property("lat", &latToDouble<ExternalMemoryNode>),
|
||||||
|
luabind::class_<util::Coordinate>("Coordinate")
|
||||||
|
.property("lon", &lonToDouble<util::Coordinate>)
|
||||||
|
.property("lat", &latToDouble<util::Coordinate>),
|
||||||
|
luabind::class_<RasterDatum>("RasterDatum")
|
||||||
|
.def_readonly("datum", &RasterDatum::datum)
|
||||||
|
.def("invalid_data", &RasterDatum::get_invalid)];
|
||||||
|
|
||||||
|
luabind::globals(context.state)["properties"] = &context.properties;
|
||||||
|
luabind::globals(context.state)["sources"] = &context.sources;
|
||||||
|
|
||||||
|
if (0 != luaL_dofile(context.state, file_name.c_str()))
|
||||||
{
|
{
|
||||||
luabind::object error_msg(luabind::from_stack(lua_state, -1));
|
luabind::object error_msg(luabind::from_stack(context.state, -1));
|
||||||
std::ostringstream error_stream;
|
std::ostringstream error_stream;
|
||||||
error_stream << error_msg;
|
error_stream << error_msg;
|
||||||
throw util::exception("ERROR occurred in profile script:\n" + error_stream.str());
|
throw util::exception("ERROR occurred in profile script:\n" + error_stream.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State *ScriptingEnvironment::GetLuaState()
|
ScriptingEnvironment::Context &ScriptingEnvironment::GetContex()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(init_mutex);
|
std::lock_guard<std::mutex> lock(init_mutex);
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
auto &ref = script_contexts.local(initialized);
|
auto &ref = script_contexts.local(initialized);
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
{
|
{
|
||||||
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
|
ref = util::make_unique<Context>();
|
||||||
ref = state;
|
InitContext(*ref);
|
||||||
InitLuaState(ref.get());
|
|
||||||
}
|
}
|
||||||
luabind::set_pcall_callback(&luaErrorCallback);
|
luabind::set_pcall_callback(&luaErrorCallback);
|
||||||
|
|
||||||
return ref.get();
|
return *ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ std::string getWrongOptionHelp(const engine::api::RouteParameters ¶meters)
|
|||||||
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "bearings",
|
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "bearings",
|
||||||
parameters.bearings, coord_size, help) ||
|
parameters.bearings, coord_size, help) ||
|
||||||
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "radiuses",
|
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "radiuses",
|
||||||
parameters.radiuses, coord_size, help) ||
|
parameters.radiuses, coord_size, help);
|
||||||
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "uturns",
|
|
||||||
parameters.uturns, coord_size, help);
|
|
||||||
|
|
||||||
if (!param_size_mismatch && parameters.coordinates.size() < 2)
|
if (!param_size_mismatch && parameters.coordinates.size() < 2)
|
||||||
{
|
{
|
||||||
|
|||||||
+69
-128
@@ -2,6 +2,7 @@
|
|||||||
#include "util/range_table.hpp"
|
#include "util/range_table.hpp"
|
||||||
#include "contractor/query_edge.hpp"
|
#include "contractor/query_edge.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
#include "util/shared_memory_vector_wrapper.hpp"
|
#include "util/shared_memory_vector_wrapper.hpp"
|
||||||
#include "util/static_graph.hpp"
|
#include "util/static_graph.hpp"
|
||||||
@@ -72,10 +73,12 @@ void deleteRegion(const SharedDataType region)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::Storage(const DataPaths &paths_) : paths(paths_) {}
|
Storage::Storage(StorageConfig config_) : config(std::move(config_)) {}
|
||||||
|
|
||||||
int Storage::Run()
|
int Storage::Run()
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT_MSG(config.IsValid(), "Invalid storage config");
|
||||||
|
|
||||||
util::LogPolicy::GetInstance().Unmute();
|
util::LogPolicy::GetInstance().Unmute();
|
||||||
SharedBarriers barrier;
|
SharedBarriers barrier;
|
||||||
|
|
||||||
@@ -99,94 +102,6 @@ int Storage::Run()
|
|||||||
barrier.pending_update_mutex.unlock();
|
barrier.pending_update_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paths.find("hsgrdata") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no hsgr file found");
|
|
||||||
}
|
|
||||||
if (paths.find("ramindex") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no ram index file found");
|
|
||||||
}
|
|
||||||
if (paths.find("fileindex") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no leaf index file found");
|
|
||||||
}
|
|
||||||
if (paths.find("nodesdata") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no nodes file found");
|
|
||||||
}
|
|
||||||
if (paths.find("edgesdata") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no edges file found");
|
|
||||||
}
|
|
||||||
if (paths.find("namesdata") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no names file found");
|
|
||||||
}
|
|
||||||
if (paths.find("geometry") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no geometry file found");
|
|
||||||
}
|
|
||||||
if (paths.find("core") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no core file found");
|
|
||||||
}
|
|
||||||
if (paths.find("datasource_indexes") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no datasource_indexes file found");
|
|
||||||
}
|
|
||||||
if (paths.find("datasource_names") == paths.end())
|
|
||||||
{
|
|
||||||
throw util::exception("no datasource_names file found");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto paths_iterator = paths.find("hsgrdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &hsgr_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("timestamp");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path ×tamp_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("ramindex");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &ram_index_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("fileindex");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path index_file_path_absolute =
|
|
||||||
boost::filesystem::canonical(paths_iterator->second);
|
|
||||||
const std::string &file_index_path = index_file_path_absolute.string();
|
|
||||||
paths_iterator = paths.find("nodesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &nodes_data_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("edgesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &edges_data_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("namesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &names_data_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("geometry");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &geometries_data_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("core");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &core_marker_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("datasource_indexes");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &datasource_indexes_path = paths_iterator->second;
|
|
||||||
paths_iterator = paths.find("datasource_names");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
|
||||||
const boost::filesystem::path &datasource_names_path = paths_iterator->second;
|
|
||||||
|
|
||||||
// determine segment to use
|
// determine segment to use
|
||||||
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
||||||
const storage::SharedDataType layout_region = [&]
|
const storage::SharedDataType layout_region = [&]
|
||||||
@@ -209,14 +124,19 @@ int Storage::Run()
|
|||||||
// Allocate a memory layout in shared memory, deallocate previous
|
// Allocate a memory layout in shared memory, deallocate previous
|
||||||
auto *layout_memory = makeSharedMemory(layout_region, sizeof(SharedDataLayout));
|
auto *layout_memory = makeSharedMemory(layout_region, sizeof(SharedDataLayout));
|
||||||
auto shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
|
auto shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
|
||||||
|
auto absolute_file_index_path = boost::filesystem::absolute(config.file_index_path);
|
||||||
|
|
||||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
|
||||||
file_index_path.length() + 1);
|
absolute_file_index_path.string().length() + 1);
|
||||||
|
|
||||||
// collect number of elements to store in shared memory object
|
// collect number of elements to store in shared memory object
|
||||||
util::SimpleLogger().Write() << "load names from: " << names_data_path;
|
util::SimpleLogger().Write() << "load names from: " << config.names_data_path;
|
||||||
// number of entries in name index
|
// number of entries in name index
|
||||||
boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
|
boost::filesystem::ifstream name_stream(config.names_data_path, std::ios::binary);
|
||||||
|
if (!name_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.names_data_path.string() + " for reading.");
|
||||||
|
}
|
||||||
unsigned name_blocks = 0;
|
unsigned name_blocks = 0;
|
||||||
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
||||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
|
||||||
@@ -230,7 +150,11 @@ int Storage::Run()
|
|||||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
||||||
|
|
||||||
// Loading information for original edges
|
// Loading information for original edges
|
||||||
boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
|
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
|
||||||
|
if (!edges_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.edges_data_path.string() + " for reading.");
|
||||||
|
}
|
||||||
unsigned number_of_original_edges = 0;
|
unsigned number_of_original_edges = 0;
|
||||||
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
|
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
|
||||||
|
|
||||||
@@ -244,7 +168,11 @@ int Storage::Run()
|
|||||||
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
|
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
|
||||||
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
|
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
|
||||||
|
|
||||||
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
|
boost::filesystem::ifstream hsgr_input_stream(config.hsgr_data_path, std::ios::binary);
|
||||||
|
if (!hsgr_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.hsgr_data_path.string() + " for reading.");
|
||||||
|
}
|
||||||
|
|
||||||
util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
|
util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
|
||||||
util::FingerPrint fingerprint_loaded;
|
util::FingerPrint fingerprint_loaded;
|
||||||
@@ -279,39 +207,27 @@ int Storage::Run()
|
|||||||
number_of_graph_edges);
|
number_of_graph_edges);
|
||||||
|
|
||||||
// load rsearch tree size
|
// load rsearch tree size
|
||||||
boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
|
boost::filesystem::ifstream tree_node_file(config.ram_index_path, std::ios::binary);
|
||||||
|
|
||||||
uint32_t tree_size = 0;
|
uint32_t tree_size = 0;
|
||||||
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
|
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
|
||||||
shared_layout_ptr->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
|
shared_layout_ptr->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
|
||||||
|
|
||||||
|
// load profile properties
|
||||||
|
shared_layout_ptr->SetBlockSize<extractor::ProfileProperties>(SharedDataLayout::PROPERTIES, 1);
|
||||||
|
|
||||||
// load timestamp size
|
// load timestamp size
|
||||||
|
boost::filesystem::ifstream timestamp_stream(config.timestamp_path);
|
||||||
std::string m_timestamp;
|
std::string m_timestamp;
|
||||||
if (boost::filesystem::exists(timestamp_path))
|
getline(timestamp_stream, m_timestamp);
|
||||||
{
|
|
||||||
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
|
||||||
if (!timestamp_stream)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logWARNING) << timestamp_path
|
|
||||||
<< " not found. setting to default";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
getline(timestamp_stream, m_timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_timestamp.empty())
|
|
||||||
{
|
|
||||||
m_timestamp = "n/a";
|
|
||||||
}
|
|
||||||
if (25 < m_timestamp.length())
|
|
||||||
{
|
|
||||||
m_timestamp.resize(25);
|
|
||||||
}
|
|
||||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
|
||||||
|
|
||||||
// load core marker size
|
// load core marker size
|
||||||
boost::filesystem::ifstream core_marker_file(core_marker_path, std::ios::binary);
|
boost::filesystem::ifstream core_marker_file(config.core_data_path, std::ios::binary);
|
||||||
|
if (!core_marker_file)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.core_data_path.string() + " for reading.");
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t number_of_core_markers = 0;
|
uint32_t number_of_core_markers = 0;
|
||||||
core_marker_file.read((char *)&number_of_core_markers, sizeof(uint32_t));
|
core_marker_file.read((char *)&number_of_core_markers, sizeof(uint32_t));
|
||||||
@@ -319,14 +235,22 @@ int Storage::Run()
|
|||||||
number_of_core_markers);
|
number_of_core_markers);
|
||||||
|
|
||||||
// load coordinate size
|
// load coordinate size
|
||||||
boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
|
boost::filesystem::ifstream nodes_input_stream(config.nodes_data_path, std::ios::binary);
|
||||||
|
if (!nodes_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.core_data_path.string() + " for reading.");
|
||||||
|
}
|
||||||
unsigned coordinate_list_size = 0;
|
unsigned coordinate_list_size = 0;
|
||||||
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
|
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
|
||||||
shared_layout_ptr->SetBlockSize<util::Coordinate>(SharedDataLayout::COORDINATE_LIST,
|
shared_layout_ptr->SetBlockSize<util::Coordinate>(SharedDataLayout::COORDINATE_LIST,
|
||||||
coordinate_list_size);
|
coordinate_list_size);
|
||||||
|
|
||||||
// load geometries sizes
|
// load geometries sizes
|
||||||
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(), std::ios::binary);
|
boost::filesystem::ifstream geometry_input_stream(config.geometries_path, std::ios::binary);
|
||||||
|
if (!geometry_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.geometries_path.string() + " for reading.");
|
||||||
|
}
|
||||||
unsigned number_of_geometries_indices = 0;
|
unsigned number_of_geometries_indices = 0;
|
||||||
unsigned number_of_compressed_geometries = 0;
|
unsigned number_of_compressed_geometries = 0;
|
||||||
|
|
||||||
@@ -341,8 +265,12 @@ int Storage::Run()
|
|||||||
|
|
||||||
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
|
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
|
||||||
// exist.
|
// exist.
|
||||||
std::ifstream geometry_datasource_input_stream(datasource_indexes_path.c_str(),
|
boost::filesystem::ifstream geometry_datasource_input_stream(config.datasource_indexes_path,
|
||||||
std::ios::binary);
|
std::ios::binary);
|
||||||
|
if (!geometry_datasource_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.datasource_indexes_path.string() + " for reading.");
|
||||||
|
}
|
||||||
std::size_t number_of_compressed_datasources = 0;
|
std::size_t number_of_compressed_datasources = 0;
|
||||||
if (geometry_datasource_input_stream)
|
if (geometry_datasource_input_stream)
|
||||||
{
|
{
|
||||||
@@ -354,7 +282,12 @@ int Storage::Run()
|
|||||||
|
|
||||||
// Load datasource name sizes. This file is optional, and it's non-fatal if it doesn't
|
// Load datasource name sizes. This file is optional, and it's non-fatal if it doesn't
|
||||||
// exist
|
// exist
|
||||||
std::ifstream datasource_names_input_stream(datasource_names_path.c_str(), std::ios::binary);
|
boost::filesystem::ifstream datasource_names_input_stream(config.datasource_names_path,
|
||||||
|
std::ios::binary);
|
||||||
|
if (!datasource_names_input_stream)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not open " + config.datasource_names_path.string() + " for reading.");
|
||||||
|
}
|
||||||
std::vector<char> m_datasource_name_data;
|
std::vector<char> m_datasource_name_data;
|
||||||
std::vector<std::size_t> m_datasource_name_offsets;
|
std::vector<std::size_t> m_datasource_name_offsets;
|
||||||
std::vector<std::size_t> m_datasource_name_lengths;
|
std::vector<std::size_t> m_datasource_name_lengths;
|
||||||
@@ -370,11 +303,11 @@ int Storage::Run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::DATASOURCE_NAME_DATA,
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::DATASOURCE_NAME_DATA,
|
||||||
m_datasource_name_data.size());
|
m_datasource_name_data.size());
|
||||||
shared_layout_ptr->SetBlockSize<std::size_t>(SharedDataLayout::DATASOURCE_NAME_OFFSETS,
|
shared_layout_ptr->SetBlockSize<std::size_t>(SharedDataLayout::DATASOURCE_NAME_OFFSETS,
|
||||||
m_datasource_name_offsets.size());
|
m_datasource_name_offsets.size());
|
||||||
shared_layout_ptr->SetBlockSize<std::size_t>(SharedDataLayout::DATASOURCE_NAME_LENGTHS,
|
shared_layout_ptr->SetBlockSize<std::size_t>(SharedDataLayout::DATASOURCE_NAME_LENGTHS,
|
||||||
m_datasource_name_lengths.size());
|
m_datasource_name_lengths.size());
|
||||||
|
|
||||||
// allocate shared memory block
|
// allocate shared memory block
|
||||||
util::SimpleLogger().Write() << "allocating shared memory of "
|
util::SimpleLogger().Write() << "allocating shared memory of "
|
||||||
@@ -397,7 +330,7 @@ int Storage::Run()
|
|||||||
file_index_path_ptr +
|
file_index_path_ptr +
|
||||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
||||||
0);
|
0);
|
||||||
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
|
std::copy(absolute_file_index_path.string().begin(), absolute_file_index_path.string().end(), file_index_path_ptr);
|
||||||
|
|
||||||
// Loading street names
|
// Loading street names
|
||||||
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
@@ -504,8 +437,7 @@ int Storage::Run()
|
|||||||
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
|
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
|
||||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
|
||||||
{
|
{
|
||||||
std::cout << "Copying "
|
std::cout << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
|
||||||
<< (m_datasource_name_data.end() - m_datasource_name_data.begin())
|
|
||||||
<< " chars into name data ptr\n";
|
<< " chars into name data ptr\n";
|
||||||
std::copy(m_datasource_name_data.begin(), m_datasource_name_data.end(),
|
std::copy(m_datasource_name_data.begin(), m_datasource_name_data.end(),
|
||||||
datasource_name_data_ptr);
|
datasource_name_data_ptr);
|
||||||
@@ -605,6 +537,15 @@ int Storage::Run()
|
|||||||
}
|
}
|
||||||
hsgr_input_stream.close();
|
hsgr_input_stream.close();
|
||||||
|
|
||||||
|
// load profile properties
|
||||||
|
auto profile_properties_ptr = shared_layout_ptr->GetBlockPtr<extractor::ProfileProperties, true>(shared_memory_ptr, SharedDataLayout::PROPERTIES);
|
||||||
|
boost::filesystem::ifstream profile_properties_stream(config.properties_path);
|
||||||
|
if (!profile_properties_stream)
|
||||||
|
{
|
||||||
|
util::exception("Could not open " + config.properties_path.string() + " for reading!");
|
||||||
|
}
|
||||||
|
profile_properties_stream.read(reinterpret_cast<char*>(profile_properties_ptr), sizeof(extractor::ProfileProperties));
|
||||||
|
|
||||||
// acquire lock
|
// acquire lock
|
||||||
SharedMemory *data_type_memory =
|
SharedMemory *data_type_memory =
|
||||||
makeSharedMemory(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
|
makeSharedMemory(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include "storage/storage_config.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem/operations.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace storage
|
||||||
|
{
|
||||||
|
|
||||||
|
StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
||||||
|
: ram_index_path{base.string() + ".ramIndex"}, file_index_path{base.string() + ".fileIndex"},
|
||||||
|
hsgr_data_path{base.string() + ".hsgr"}, nodes_data_path{base.string() + ".nodes"},
|
||||||
|
edges_data_path{base.string() + ".edges"}, core_data_path{base.string() + ".core"},
|
||||||
|
geometries_path{base.string() + ".geometry"}, timestamp_path{base.string() + ".timestamp"},
|
||||||
|
datasource_names_path{base.string() + ".datasource_names"},
|
||||||
|
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
||||||
|
names_data_path{base.string() + ".names"},
|
||||||
|
properties_path{base.string() + ".properties"}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StorageConfig::IsValid() const
|
||||||
|
{
|
||||||
|
return boost::filesystem::is_regular_file(ram_index_path) &&
|
||||||
|
boost::filesystem::is_regular_file(file_index_path) &&
|
||||||
|
boost::filesystem::is_regular_file(hsgr_data_path) &&
|
||||||
|
boost::filesystem::is_regular_file(nodes_data_path) &&
|
||||||
|
boost::filesystem::is_regular_file(edges_data_path) &&
|
||||||
|
boost::filesystem::is_regular_file(core_data_path) &&
|
||||||
|
boost::filesystem::is_regular_file(geometries_path) &&
|
||||||
|
boost::filesystem::is_regular_file(timestamp_path) &&
|
||||||
|
boost::filesystem::is_regular_file(datasource_names_path) &&
|
||||||
|
boost::filesystem::is_regular_file(datasource_indexes_path) &&
|
||||||
|
boost::filesystem::is_regular_file(names_data_path) &&
|
||||||
|
boost::filesystem::is_regular_file(properties_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+132
-5
@@ -1,10 +1,14 @@
|
|||||||
#include "server/server.hpp"
|
#include "server/server.hpp"
|
||||||
#include "util/routed_options.hpp"
|
|
||||||
#include "util/make_unique.hpp"
|
#include "util/make_unique.hpp"
|
||||||
#include "util/simple_logger.hpp"
|
#include "util/simple_logger.hpp"
|
||||||
|
#include "util/version.hpp"
|
||||||
|
|
||||||
#include "osrm/osrm.hpp"
|
#include "osrm/osrm.hpp"
|
||||||
#include "osrm/engine_config.hpp"
|
#include "osrm/engine_config.hpp"
|
||||||
|
#include "osrm/storage_config.hpp"
|
||||||
|
|
||||||
|
#include <boost/any.hpp>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@@ -19,6 +23,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
boost::function0<void> console_ctrl_function;
|
boost::function0<void> console_ctrl_function;
|
||||||
@@ -41,6 +46,111 @@ BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
|
|||||||
|
|
||||||
using namespace osrm;
|
using namespace osrm;
|
||||||
|
|
||||||
|
const static unsigned INIT_OK_START_ENGINE = 0;
|
||||||
|
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
|
||||||
|
const static unsigned INIT_FAILED = -1;
|
||||||
|
|
||||||
|
// generate boost::program_options object for the routing part
|
||||||
|
inline unsigned
|
||||||
|
generateServerProgramOptions(const int argc,
|
||||||
|
const char *argv[],
|
||||||
|
boost::filesystem::path &base_path,
|
||||||
|
std::string &ip_address,
|
||||||
|
int &ip_port,
|
||||||
|
int &requested_num_threads,
|
||||||
|
bool &use_shared_memory,
|
||||||
|
bool &trial,
|
||||||
|
int &max_locations_trip,
|
||||||
|
int &max_locations_viaroute,
|
||||||
|
int &max_locations_distance_table,
|
||||||
|
int &max_locations_map_matching)
|
||||||
|
{
|
||||||
|
using boost::program_options::value;
|
||||||
|
using boost::filesystem::path;
|
||||||
|
|
||||||
|
// declare a group of options that will be allowed only on command line
|
||||||
|
boost::program_options::options_description generic_options("Options");
|
||||||
|
generic_options.add_options() //
|
||||||
|
("version,v", "Show version")("help,h", "Show this help message") //
|
||||||
|
("trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
|
||||||
|
|
||||||
|
// declare a group of options that will be allowed on command line
|
||||||
|
boost::program_options::options_description config_options("Configuration");
|
||||||
|
config_options.add_options() //
|
||||||
|
("ip,i", value<std::string>(&ip_address)->default_value("0.0.0.0"),
|
||||||
|
"IP address") //
|
||||||
|
("port,p", value<int>(&ip_port)->default_value(5000),
|
||||||
|
"TCP/IP port") //
|
||||||
|
("threads,t", value<int>(&requested_num_threads)->default_value(8),
|
||||||
|
"Number of threads to use") //
|
||||||
|
("shared-memory,s",
|
||||||
|
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false),
|
||||||
|
"Load data from shared memory") //
|
||||||
|
("max-viaroute-size", value<int>(&max_locations_viaroute)->default_value(500),
|
||||||
|
"Max. locations supported in viaroute query") //
|
||||||
|
("max-trip-size", value<int>(&max_locations_trip)->default_value(100),
|
||||||
|
"Max. locations supported in trip query") //
|
||||||
|
("max-table-size", value<int>(&max_locations_distance_table)->default_value(100),
|
||||||
|
"Max. locations supported in distance table query") //
|
||||||
|
("max-matching-size", value<int>(&max_locations_map_matching)->default_value(100),
|
||||||
|
"Max. locations supported in map matching query");
|
||||||
|
|
||||||
|
// hidden options, will be allowed on command line, but will not be shown to the user
|
||||||
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
|
hidden_options.add_options()("base,b", value<boost::filesystem::path>(&base_path),
|
||||||
|
"base path to .osrm file");
|
||||||
|
|
||||||
|
// positional option
|
||||||
|
boost::program_options::positional_options_description positional_options;
|
||||||
|
positional_options.add("base", 1);
|
||||||
|
|
||||||
|
// combine above options for parsing
|
||||||
|
boost::program_options::options_description cmdline_options;
|
||||||
|
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description visible_options(
|
||||||
|
boost::filesystem::path(argv[0]).stem().string() + " <base.osrm> [<options>]");
|
||||||
|
visible_options.add(generic_options).add(config_options);
|
||||||
|
|
||||||
|
// parse command line options
|
||||||
|
boost::program_options::variables_map option_variables;
|
||||||
|
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||||
|
.options(cmdline_options)
|
||||||
|
.positional(positional_options)
|
||||||
|
.run(),
|
||||||
|
option_variables);
|
||||||
|
|
||||||
|
if (option_variables.count("version"))
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write() << OSRM_VERSION;
|
||||||
|
return INIT_OK_DO_NOT_START_ENGINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option_variables.count("help"))
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write() << visible_options;
|
||||||
|
return INIT_OK_DO_NOT_START_ENGINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
|
if (!use_shared_memory && option_variables.count("base"))
|
||||||
|
{
|
||||||
|
return INIT_OK_START_ENGINE;
|
||||||
|
}
|
||||||
|
else if (use_shared_memory && !option_variables.count("base"))
|
||||||
|
{
|
||||||
|
return INIT_OK_START_ENGINE;
|
||||||
|
}
|
||||||
|
else if (use_shared_memory && option_variables.count("base"))
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << "Shared memory settings conflict with path settings.";
|
||||||
|
}
|
||||||
|
|
||||||
|
util::SimpleLogger().Write() << visible_options;
|
||||||
|
return INIT_OK_DO_NOT_START_ENGINE;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) try
|
int main(int argc, const char *argv[]) try
|
||||||
{
|
{
|
||||||
util::LogPolicy::GetInstance().Unmute();
|
util::LogPolicy::GetInstance().Unmute();
|
||||||
@@ -50,19 +160,36 @@ int main(int argc, const char *argv[]) try
|
|||||||
int ip_port, requested_thread_num;
|
int ip_port, requested_thread_num;
|
||||||
|
|
||||||
EngineConfig config;
|
EngineConfig config;
|
||||||
const unsigned init_result = util::GenerateServerProgramOptions(
|
boost::filesystem::path base_path;
|
||||||
argc, argv, config.server_paths, ip_address, ip_port, requested_thread_num,
|
const unsigned init_result = generateServerProgramOptions(
|
||||||
|
argc, argv, base_path, ip_address, ip_port, requested_thread_num,
|
||||||
config.use_shared_memory, trial_run, config.max_locations_trip,
|
config.use_shared_memory, trial_run, config.max_locations_trip,
|
||||||
config.max_locations_viaroute, config.max_locations_distance_table,
|
config.max_locations_viaroute, config.max_locations_distance_table,
|
||||||
config.max_locations_map_matching);
|
config.max_locations_map_matching);
|
||||||
if (init_result == util::INIT_OK_DO_NOT_START_ENGINE)
|
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
|
||||||
{
|
{
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
if (init_result == util::INIT_FAILED)
|
if (init_result == INIT_FAILED)
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (!base_path.empty())
|
||||||
|
{
|
||||||
|
config.storage_config = storage::StorageConfig(base_path);
|
||||||
|
}
|
||||||
|
if(!config.IsValid())
|
||||||
|
{
|
||||||
|
if (base_path.empty() != config.use_shared_memory)
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << "Path settings and shared memory conflicts.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << "Invalid config options.";
|
||||||
|
}
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
struct MemoryLocker final
|
struct MemoryLocker final
|
||||||
|
|||||||
+11
-157
@@ -10,7 +10,7 @@
|
|||||||
using namespace osrm;
|
using namespace osrm;
|
||||||
|
|
||||||
// generate boost::program_options object for the routing part
|
// generate boost::program_options object for the routing part
|
||||||
bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataPaths &paths)
|
bool generateDataStoreOptions(const int argc, const char *argv[], boost::filesystem::path& base_path)
|
||||||
{
|
{
|
||||||
// declare a group of options that will be allowed only on command line
|
// declare a group of options that will be allowed only on command line
|
||||||
boost::program_options::options_description generic_options("Options");
|
boost::program_options::options_description generic_options("Options");
|
||||||
@@ -20,36 +20,11 @@ bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataP
|
|||||||
// declare a group of options that will be allowed both on command line
|
// declare a group of options that will be allowed both on command line
|
||||||
// as well as in a config file
|
// as well as in a config file
|
||||||
boost::program_options::options_description config_options("Configuration");
|
boost::program_options::options_description config_options("Configuration");
|
||||||
config_options.add_options()(
|
|
||||||
"hsgrdata", boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
|
|
||||||
".hsgr file")("nodesdata",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
|
|
||||||
".nodes file")(
|
|
||||||
"edgesdata", boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
|
||||||
".edges file")("geometry",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
|
|
||||||
".geometry file")(
|
|
||||||
"ramindex", boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
|
|
||||||
".ramIndex file")(
|
|
||||||
"fileindex", boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
|
|
||||||
".fileIndex file")("core",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["core"]),
|
|
||||||
".core file")(
|
|
||||||
"namesdata", boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
|
|
||||||
".names file")("timestamp",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
|
|
||||||
".timestamp file")(
|
|
||||||
"datasource_names",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["datasource_names"]),
|
|
||||||
".datasource_names file")(
|
|
||||||
"datasource_indexes",
|
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["datasource_indexes"]),
|
|
||||||
".datasource_indexes file");
|
|
||||||
|
|
||||||
// hidden options, will be allowed on command line but will not be shown to the user
|
// hidden options, will be allowed on command line but will not be shown to the user
|
||||||
boost::program_options::options_description hidden_options("Hidden options");
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
hidden_options.add_options()(
|
hidden_options.add_options()(
|
||||||
"base,b", boost::program_options::value<boost::filesystem::path>(&paths["base"]),
|
"base,b", boost::program_options::value<boost::filesystem::path>(&base_path),
|
||||||
"base path to .osrm file");
|
"base path to .osrm file");
|
||||||
|
|
||||||
// positional option
|
// positional option
|
||||||
@@ -93,132 +68,6 @@ bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataP
|
|||||||
|
|
||||||
boost::program_options::notify(option_variables);
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
auto path_iterator = paths.find("base");
|
|
||||||
BOOST_ASSERT(paths.end() != path_iterator);
|
|
||||||
std::string base_string = path_iterator->second.string();
|
|
||||||
|
|
||||||
path_iterator = paths.find("hsgrdata");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".hsgr";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("nodesdata");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".nodes";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("edgesdata");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".edges";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("geometry");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".geometry";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("ramindex");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".ramIndex";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("fileindex");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".fileIndex";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("core");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".core";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("namesdata");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".names";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("timestamp");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".timestamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("datasource_indexes");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".datasource_indexes";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("datasource_names");
|
|
||||||
if (path_iterator != paths.end())
|
|
||||||
{
|
|
||||||
path_iterator->second = base_string + ".datasource_names";
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("hsgrdata");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .hsgr file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("nodesdata");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .nodes file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("edgesdata");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .edges file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("geometry");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .geometry file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("ramindex");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .ramindex file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("fileindex");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .fileindex file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("namesdata");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .names file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
path_iterator = paths.find("timestamp");
|
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
|
||||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
|
||||||
{
|
|
||||||
throw util::exception("valid .timestamp file must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,13 +75,18 @@ int main(const int argc, const char *argv[]) try
|
|||||||
{
|
{
|
||||||
util::LogPolicy::GetInstance().Unmute();
|
util::LogPolicy::GetInstance().Unmute();
|
||||||
|
|
||||||
storage::DataPaths paths;
|
boost::filesystem::path base_path;
|
||||||
if (!generateDataStoreOptions(argc, argv, paths))
|
if (!generateDataStoreOptions(argc, argv, base_path))
|
||||||
{
|
{
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
storage::StorageConfig config(base_path);
|
||||||
storage::Storage storage(paths);
|
if (!config.IsValid())
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << "Invalid file path given!";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
storage::Storage storage(std::move(config));
|
||||||
return storage.Run();
|
return storage.Run();
|
||||||
}
|
}
|
||||||
catch (const std::bad_alloc &e)
|
catch (const std::bad_alloc &e)
|
||||||
|
|||||||
@@ -29,20 +29,6 @@ Coordinate::Coordinate(const FloatLongitude lon_, const FloatLatitude lat_)
|
|||||||
|
|
||||||
Coordinate::Coordinate(const FixedLongitude lon_, const FixedLatitude lat_) : lon(lon_), lat(lat_)
|
Coordinate::Coordinate(const FixedLongitude lon_, const FixedLatitude lat_) : lon(lon_), lat(lat_)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
if (0 != (std::abs(static_cast<int>(lon)) >> 30))
|
|
||||||
{
|
|
||||||
std::bitset<32> x_coordinate_vector(static_cast<int>(lon));
|
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
|
||||||
<< ", bits: " << x_coordinate_vector;
|
|
||||||
}
|
|
||||||
if (0 != (std::abs(static_cast<int>(lat)) >> 30))
|
|
||||||
{
|
|
||||||
std::bitset<32> y_coordinate_vector(static_cast<int>(lat));
|
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
|
||||||
<< ", bits: " << y_coordinate_vector;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Coordinate::IsValid() const
|
bool Coordinate::IsValid() const
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "util/trigonometry_table.hpp"
|
#include "util/trigonometry_table.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/math/constants/constants.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -14,6 +13,7 @@ namespace osrm
|
|||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace coordinate_calculation
|
namespace coordinate_calculation
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -43,11 +43,11 @@ double haversineDistance(const Coordinate coordinate_1, const Coordinate coordin
|
|||||||
const double ln1 = lon1 / COORDINATE_PRECISION;
|
const double ln1 = lon1 / COORDINATE_PRECISION;
|
||||||
const double lt2 = lat2 / COORDINATE_PRECISION;
|
const double lt2 = lat2 / COORDINATE_PRECISION;
|
||||||
const double ln2 = lon2 / COORDINATE_PRECISION;
|
const double ln2 = lon2 / COORDINATE_PRECISION;
|
||||||
const double dlat1 = lt1 * (RAD);
|
const double dlat1 = lt1 * DEGREE_TO_RAD;
|
||||||
|
|
||||||
const double dlong1 = ln1 * (RAD);
|
const double dlong1 = ln1 * DEGREE_TO_RAD;
|
||||||
const double dlat2 = lt2 * (RAD);
|
const double dlat2 = lt2 * DEGREE_TO_RAD;
|
||||||
const double dlong2 = ln2 * (RAD);
|
const double dlong2 = ln2 * DEGREE_TO_RAD;
|
||||||
|
|
||||||
const double dlong = dlong1 - dlong2;
|
const double dlong = dlong1 - dlong2;
|
||||||
const double dlat = dlat1 - dlat2;
|
const double dlat = dlat1 - dlat2;
|
||||||
@@ -69,10 +69,10 @@ double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coord
|
|||||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
|
|
||||||
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
|
||||||
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
|
||||||
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
|
||||||
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
|
||||||
|
|
||||||
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
|
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
|
||||||
const double y_value = float_lat2 - float_lat1;
|
const double y_value = float_lat2 - float_lat1;
|
||||||
@@ -269,22 +269,84 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
|
|||||||
|
|
||||||
namespace mercator
|
namespace mercator
|
||||||
{
|
{
|
||||||
FloatLatitude yToLat(const double value)
|
FloatLatitude yToLat(const double y)
|
||||||
{
|
{
|
||||||
using namespace boost::math::constants;
|
const double normalized_lat = RAD_TO_DEGREE * 2. * std::atan(std::exp(y * DEGREE_TO_RAD));
|
||||||
|
|
||||||
return FloatLatitude(
|
return FloatLatitude(normalized_lat - 90.);
|
||||||
180. * (1. / pi<long double>()) *
|
|
||||||
(2. * std::atan(std::exp(value * pi<double>() / 180.)) - half_pi<double>()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double latToY(const FloatLatitude latitude)
|
double latToY(const FloatLatitude latitude)
|
||||||
{
|
{
|
||||||
using namespace boost::math::constants;
|
const double normalized_lat = 90. + static_cast<double>(latitude);
|
||||||
|
|
||||||
return 180. * (1. / pi<double>()) *
|
return RAD_TO_DEGREE * std::log(std::tan(normalized_lat * DEGREE_TO_RAD * 0.5));
|
||||||
std::log(std::tan((pi<double>() / 4.) +
|
}
|
||||||
static_cast<double>(latitude) * (pi<double>() / 180.) / 2.));
|
|
||||||
|
FloatLatitude clamp(const FloatLatitude lat)
|
||||||
|
{
|
||||||
|
return std::max(std::min(lat, FloatLatitude(detail::MAX_LATITUDE)),
|
||||||
|
FloatLatitude(-detail::MAX_LATITUDE));
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatLongitude clamp(const FloatLongitude lon)
|
||||||
|
{
|
||||||
|
return std::max(std::min(lon, FloatLongitude(detail::MAX_LONGITUDE)),
|
||||||
|
FloatLongitude(-detail::MAX_LONGITUDE));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void pixelToDegree(const double shift, double &x, double &y)
|
||||||
|
{
|
||||||
|
const double b = shift / 2.0;
|
||||||
|
x = (x - b) / shift * 360.0;
|
||||||
|
// FIXME needs to be simplified
|
||||||
|
const double g = (y - b) / -(shift / (2 * M_PI)) / DEGREE_TO_RAD;
|
||||||
|
static_assert(DEGREE_TO_RAD / (2 * M_PI) - 1/360. < 0.0001, "");
|
||||||
|
y = static_cast<double>(util::coordinate_calculation::mercator::yToLat(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
double degreeToPixel(FloatLongitude lon, unsigned zoom)
|
||||||
|
{
|
||||||
|
const double shift = (1u << zoom) * TILE_SIZE;
|
||||||
|
const double b = shift / 2.0;
|
||||||
|
const double x = b * (1 + static_cast<double>(lon) / 180.0);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
double degreeToPixel(FloatLatitude lat, unsigned zoom)
|
||||||
|
{
|
||||||
|
const double shift = (1u << zoom) * TILE_SIZE;
|
||||||
|
const double b = shift / 2.0;
|
||||||
|
const double y = b * (1. - latToY(lat) / 180.);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a WMS tile coordinate (z,x,y) into a wsg84 bounding box
|
||||||
|
void xyzToWSG84(const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy)
|
||||||
|
{
|
||||||
|
using util::coordinate_calculation::mercator::TILE_SIZE;
|
||||||
|
|
||||||
|
minx = x * TILE_SIZE;
|
||||||
|
miny = (y + 1.0) * TILE_SIZE;
|
||||||
|
maxx = (x + 1.0) * TILE_SIZE;
|
||||||
|
maxy = y * TILE_SIZE;
|
||||||
|
// 2^z * TILE_SIZE
|
||||||
|
const double shift = (1u << static_cast<unsigned>(z)) * TILE_SIZE;
|
||||||
|
pixelToDegree(shift, minx, miny);
|
||||||
|
pixelToDegree(shift, maxx, maxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a WMS tile coordinate (z,x,y) into a mercator bounding box
|
||||||
|
void xyzToMercator(const int x, const int y, const int z, double &minx, double &miny, double &maxx, double &maxy)
|
||||||
|
{
|
||||||
|
using namespace util::coordinate_calculation::mercator;
|
||||||
|
|
||||||
|
xyzToWSG84(x, y, z, minx, miny, maxx, maxy);
|
||||||
|
|
||||||
|
minx = static_cast<double>(clamp(util::FloatLongitude(minx))) * DEGREE_TO_PX;
|
||||||
|
miny = latToY(clamp(util::FloatLatitude(miny))) * DEGREE_TO_PX;
|
||||||
|
maxx = static_cast<double>(clamp(util::FloatLongitude(maxx))) * DEGREE_TO_PX;
|
||||||
|
maxy = latToY(clamp(util::FloatLatitude(maxy))) * DEGREE_TO_PX;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ns mercato // ns mercatorr
|
} // ns mercato // ns mercatorr
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#include "util/name_table.hpp"
|
||||||
|
#include "util/simple_logger.hpp"
|
||||||
|
#include "util/exception.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
|
||||||
|
NameTable::NameTable(const std::string &filename)
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream name_stream(filename, std::ios::binary);
|
||||||
|
|
||||||
|
if( !name_stream )
|
||||||
|
throw exception("Failed to open " + filename + " for reading.");
|
||||||
|
|
||||||
|
name_stream >> m_name_table;
|
||||||
|
|
||||||
|
unsigned number_of_chars = 0;
|
||||||
|
name_stream.read(reinterpret_cast<char *>(&number_of_chars), sizeof(number_of_chars));
|
||||||
|
if( !name_stream )
|
||||||
|
throw exception("Encountered invalid file, failed to read number of contained chars");
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
|
||||||
|
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
|
||||||
|
name_stream.read(reinterpret_cast<char *>(&m_names_char_list[0]),
|
||||||
|
number_of_chars * sizeof(m_names_char_list[0]));
|
||||||
|
if( !name_stream )
|
||||||
|
throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from file.");
|
||||||
|
|
||||||
|
if (0 == m_names_char_list.size())
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logWARNING) << "list of street names is empty";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NameTable::GetNameForID(const unsigned name_id) const
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<unsigned>::max() == name_id)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
auto range = m_name_table.GetRange(name_id);
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
result.reserve(range.size());
|
||||||
|
if (range.begin() != range.end())
|
||||||
|
{
|
||||||
|
result.resize(range.back() - range.front() + 1);
|
||||||
|
std::copy(m_names_char_list.begin() + range.front(),
|
||||||
|
m_names_char_list.begin() + range.back() + 1, result.begin());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace util
|
||||||
|
} // namespace osrm
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#include "engine/base64.hpp"
|
||||||
|
#include "engine/hint.hpp"
|
||||||
|
#include "mocks/mock_datafacade.hpp"
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <boost/test/test_case_template.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
|
||||||
|
BOOST_AUTO_TEST_SUITE(base64)
|
||||||
|
|
||||||
|
// For test vectors see section 10: https://tools.ietf.org/html/rfc4648#section-10
|
||||||
|
BOOST_AUTO_TEST_CASE(rfc4648_test_vectors)
|
||||||
|
{
|
||||||
|
using namespace osrm::engine;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64(""), "");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("f"), "Zg==");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("fo"), "Zm8=");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("foo"), "Zm9v");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("foob"), "Zm9vYg==");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("fooba"), "Zm9vYmE=");
|
||||||
|
BOOST_CHECK_EQUAL(encodeBase64("foobar"), "Zm9vYmFy");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(rfc4648_test_vectors_roundtrip)
|
||||||
|
{
|
||||||
|
using namespace osrm::engine;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("")), "");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("f")), "f");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fo")), "fo");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foo")), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foob")), "foob");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fooba")), "fooba");
|
||||||
|
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foobar")), "foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip)
|
||||||
|
{
|
||||||
|
using namespace osrm::engine;
|
||||||
|
|
||||||
|
osrm::test::MockDataFacade facade;
|
||||||
|
|
||||||
|
Hint hint{{}, {}, facade.GetCheckSum()};
|
||||||
|
|
||||||
|
const auto base64 = hint.ToBase64();
|
||||||
|
|
||||||
|
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '+'));
|
||||||
|
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '/'));
|
||||||
|
|
||||||
|
const auto decoded = Hint::FromBase64(base64);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(hint, decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip_bytewise)
|
||||||
|
{
|
||||||
|
using namespace osrm::engine;
|
||||||
|
|
||||||
|
osrm::test::MockDataFacade facade;
|
||||||
|
|
||||||
|
Hint hint{{}, {}, facade.GetCheckSum()};
|
||||||
|
|
||||||
|
const auto decoded = Hint::FromBase64(hint.ToBase64());
|
||||||
|
|
||||||
|
BOOST_CHECK(std::equal(reinterpret_cast<const unsigned char *>(&hint),
|
||||||
|
reinterpret_cast<const unsigned char *>(&hint) + sizeof(Hint),
|
||||||
|
reinterpret_cast<const unsigned char *>(&decoded)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
@@ -103,6 +103,7 @@ class MockDataFacadeT final : public osrm::engine::datafacade::BaseDataFacade<Ed
|
|||||||
std::string get_name_for_id(const unsigned /* name_id */) const { return ""; }
|
std::string get_name_for_id(const unsigned /* name_id */) const { return ""; }
|
||||||
std::size_t GetCoreSize() const { return 0; }
|
std::size_t GetCoreSize() const { return 0; }
|
||||||
std::string GetTimestamp() const { return ""; }
|
std::string GetTimestamp() const { return ""; }
|
||||||
|
bool GetUTurnsDefault() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using MockDataFacade = MockDataFacadeT<contractor::QueryEdge::EdgeData>;
|
using MockDataFacade = MockDataFacadeT<contractor::QueryEdge::EdgeData>;
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
BOOST_CHECK_EQUAL(reference_1.alternatives, result_1->alternatives);
|
BOOST_CHECK_EQUAL(reference_1.alternatives, result_1->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_1.geometries, result_1->geometries);
|
BOOST_CHECK_EQUAL(reference_1.geometries, result_1->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_1.overview, result_1->overview);
|
BOOST_CHECK_EQUAL(reference_1.overview, result_1->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_1.uturns, result_1->uturns);
|
BOOST_CHECK_EQUAL(reference_1.uturns, result_1->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
|
CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
|
CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
|
CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
|
||||||
@@ -146,25 +146,26 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
BOOST_CHECK_EQUAL(reference_2.alternatives, result_2->alternatives);
|
BOOST_CHECK_EQUAL(reference_2.alternatives, result_2->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_2.geometries, result_2->geometries);
|
BOOST_CHECK_EQUAL(reference_2.geometries, result_2->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_2.overview, result_2->overview);
|
BOOST_CHECK_EQUAL(reference_2.overview, result_2->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_2.uturns, result_2->uturns);
|
BOOST_CHECK_EQUAL(reference_2.uturns, result_2->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
|
CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
|
CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
|
CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
|
||||||
|
|
||||||
std::vector<boost::optional<bool>> uturns_3 = {true, false, boost::none};
|
engine::api::RouteParameters reference_3{false,
|
||||||
engine::api::RouteParameters reference_3{
|
false,
|
||||||
false, false, engine::api::RouteParameters::GeometriesType::GeoJSON,
|
engine::api::RouteParameters::GeometriesType::GeoJSON,
|
||||||
engine::api::RouteParameters::OverviewType::False, uturns_3};
|
engine::api::RouteParameters::OverviewType::False,
|
||||||
|
true};
|
||||||
reference_3.coordinates = coords_1;
|
reference_3.coordinates = coords_1;
|
||||||
auto result_3 = api::parseParameters<engine::api::RouteParameters>(
|
auto result_3 = api::parseParameters<engine::api::RouteParameters>(
|
||||||
"1,2;3,4?steps=false&alternatives=false&geometries=geojson&overview=false&uturns=true;"
|
"1,2;3,4?steps=false&alternatives=false&geometries=geojson&overview=false&uturns=true"
|
||||||
"false;");
|
"false;");
|
||||||
BOOST_CHECK(result_3);
|
BOOST_CHECK(result_3);
|
||||||
BOOST_CHECK_EQUAL(reference_3.steps, result_3->steps);
|
BOOST_CHECK_EQUAL(reference_3.steps, result_3->steps);
|
||||||
BOOST_CHECK_EQUAL(reference_3.alternatives, result_3->alternatives);
|
BOOST_CHECK_EQUAL(reference_3.alternatives, result_3->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_3.geometries, result_3->geometries);
|
BOOST_CHECK_EQUAL(reference_3.geometries, result_3->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_3.overview, result_3->overview);
|
BOOST_CHECK_EQUAL(reference_3.overview, result_3->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_3.uturns, result_3->uturns);
|
BOOST_CHECK_EQUAL(reference_3.uturns, result_3->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_3.bearings, result_3->bearings);
|
CHECK_EQUAL_RANGE(reference_3.bearings, result_3->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_3.radiuses, result_3->radiuses);
|
CHECK_EQUAL_RANGE(reference_3.radiuses, result_3->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_3.coordinates, result_3->coordinates);
|
CHECK_EQUAL_RANGE(reference_3.coordinates, result_3->coordinates);
|
||||||
@@ -180,7 +181,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
true,
|
true,
|
||||||
engine::api::RouteParameters::GeometriesType::Polyline,
|
engine::api::RouteParameters::GeometriesType::Polyline,
|
||||||
engine::api::RouteParameters::OverviewType::Simplified,
|
engine::api::RouteParameters::OverviewType::Simplified,
|
||||||
std::vector<boost::optional<bool>>{},
|
boost::optional<bool>{},
|
||||||
coords_1,
|
coords_1,
|
||||||
hints_4,
|
hints_4,
|
||||||
std::vector<boost::optional<double>>{},
|
std::vector<boost::optional<double>>{},
|
||||||
@@ -196,7 +197,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
|
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_4.geometries, result_4->geometries);
|
BOOST_CHECK_EQUAL(reference_4.geometries, result_4->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_4.overview, result_4->overview);
|
BOOST_CHECK_EQUAL(reference_4.overview, result_4->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_4.uturns, result_4->uturns);
|
BOOST_CHECK_EQUAL(reference_4.uturns, result_4->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_4.bearings, result_4->bearings);
|
CHECK_EQUAL_RANGE(reference_4.bearings, result_4->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_4.radiuses, result_4->radiuses);
|
CHECK_EQUAL_RANGE(reference_4.radiuses, result_4->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates);
|
CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates);
|
||||||
@@ -208,7 +209,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
true,
|
true,
|
||||||
engine::api::RouteParameters::GeometriesType::Polyline,
|
engine::api::RouteParameters::GeometriesType::Polyline,
|
||||||
engine::api::RouteParameters::OverviewType::Simplified,
|
engine::api::RouteParameters::OverviewType::Simplified,
|
||||||
std::vector<boost::optional<bool>>{},
|
boost::optional<bool>{},
|
||||||
coords_1,
|
coords_1,
|
||||||
std::vector<boost::optional<engine::Hint>>{},
|
std::vector<boost::optional<engine::Hint>>{},
|
||||||
std::vector<boost::optional<double>>{},
|
std::vector<boost::optional<double>>{},
|
||||||
@@ -220,7 +221,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
BOOST_CHECK_EQUAL(reference_5.alternatives, result_5->alternatives);
|
BOOST_CHECK_EQUAL(reference_5.alternatives, result_5->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_5.geometries, result_5->geometries);
|
BOOST_CHECK_EQUAL(reference_5.geometries, result_5->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_5.overview, result_5->overview);
|
BOOST_CHECK_EQUAL(reference_5.overview, result_5->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_5.uturns, result_5->uturns);
|
BOOST_CHECK_EQUAL(reference_5.uturns, result_5->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_5.bearings, result_5->bearings);
|
CHECK_EQUAL_RANGE(reference_5.bearings, result_5->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_5.radiuses, result_5->radiuses);
|
CHECK_EQUAL_RANGE(reference_5.radiuses, result_5->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_5.coordinates, result_5->coordinates);
|
CHECK_EQUAL_RANGE(reference_5.coordinates, result_5->coordinates);
|
||||||
@@ -238,7 +239,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
BOOST_CHECK_EQUAL(reference_6.alternatives, result_6->alternatives);
|
BOOST_CHECK_EQUAL(reference_6.alternatives, result_6->alternatives);
|
||||||
BOOST_CHECK_EQUAL(reference_6.geometries, result_6->geometries);
|
BOOST_CHECK_EQUAL(reference_6.geometries, result_6->geometries);
|
||||||
BOOST_CHECK_EQUAL(reference_6.overview, result_6->overview);
|
BOOST_CHECK_EQUAL(reference_6.overview, result_6->overview);
|
||||||
CHECK_EQUAL_RANGE(reference_6.uturns, result_6->uturns);
|
BOOST_CHECK_EQUAL(reference_6.uturns, result_6->uturns);
|
||||||
CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
|
CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
|
||||||
CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
|
CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
|
||||||
CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
|
CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
|
||||||
|
|||||||
@@ -24,3 +24,69 @@ BOOST_AUTO_TEST_CASE(regression_test_1347)
|
|||||||
|
|
||||||
BOOST_CHECK_LE(std::abs(d1 - d2), 0.01);
|
BOOST_CHECK_LE(std::abs(d1 - d2), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(lon_to_pixel)
|
||||||
|
{
|
||||||
|
using namespace coordinate_calculation;
|
||||||
|
BOOST_CHECK_CLOSE(7.416042 * mercator::DEGREE_TO_PX, 825550.019142, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(7.415892 * mercator::DEGREE_TO_PX, 825533.321218, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(7.416016 * mercator::DEGREE_TO_PX, 825547.124835, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(7.41577 * mercator::DEGREE_TO_PX, 825519.74024, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(7.415808 * mercator::DEGREE_TO_PX, 825523.970381, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(lat_to_pixel)
|
||||||
|
{
|
||||||
|
using namespace coordinate_calculation;
|
||||||
|
BOOST_CHECK_CLOSE(mercator::latToY(util::FloatLatitude(43.733947)) * mercator::DEGREE_TO_PX,
|
||||||
|
5424361.75863, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(mercator::latToY(util::FloatLatitude(43.733799)) * mercator::DEGREE_TO_PX,
|
||||||
|
5424338.95731, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(mercator::latToY(util::FloatLatitude(43.733922)) * mercator::DEGREE_TO_PX,
|
||||||
|
5424357.90705, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(mercator::latToY(util::FloatLatitude(43.733697)) * mercator::DEGREE_TO_PX,
|
||||||
|
5424323.24293, 0.1);
|
||||||
|
BOOST_CHECK_CLOSE(mercator::latToY(util::FloatLatitude(43.733729)) * mercator::DEGREE_TO_PX,
|
||||||
|
5424328.17293, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(xyz_to_wgs84)
|
||||||
|
{
|
||||||
|
using namespace coordinate_calculation;
|
||||||
|
|
||||||
|
double minx_1;
|
||||||
|
double miny_1;
|
||||||
|
double maxx_1;
|
||||||
|
double maxy_1;
|
||||||
|
mercator::xyzToWSG84(2, 2, 1, minx_1, miny_1, maxx_1, maxy_1);
|
||||||
|
BOOST_CHECK_CLOSE(minx_1, 180, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(miny_1, -89.786, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxx_1, 360, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxy_1, -85.0511, 0.0001);
|
||||||
|
|
||||||
|
double minx_2;
|
||||||
|
double miny_2;
|
||||||
|
double maxx_2;
|
||||||
|
double maxy_2;
|
||||||
|
mercator::xyzToWSG84(100, 0, 13, minx_2, miny_2, maxx_2, maxy_2);
|
||||||
|
BOOST_CHECK_CLOSE(minx_2, -175.6054, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(miny_2, 85.0473, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxx_2, -175.5615, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxy_2, 85.0511, 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(xyz_to_mercator)
|
||||||
|
{
|
||||||
|
using namespace coordinate_calculation;
|
||||||
|
|
||||||
|
double minx;
|
||||||
|
double miny;
|
||||||
|
double maxx;
|
||||||
|
double maxy;
|
||||||
|
mercator::xyzToMercator(100, 0, 13, minx, miny, maxx, maxy);
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE(minx, -19548311.361764118075, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(miny, 20032616.372979003936, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxx, -19543419.391953866929, 0.0001);
|
||||||
|
BOOST_CHECK_CLOSE(maxy, 20037508.342789277434, 0.0001);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "util/tiles.hpp"
|
|
||||||
|
|
||||||
using namespace osrm::util;
|
|
||||||
|
|
||||||
#include <boost/functional/hash.hpp>
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
#include <boost/test/test_case_template.hpp>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(tiles_test)
|
|
||||||
|
|
||||||
using namespace osrm;
|
|
||||||
using namespace osrm::util;
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(point_to_tile_test)
|
|
||||||
{
|
|
||||||
tiles::Tile tile_1_reference{2306375680, 1409941503, 32};
|
|
||||||
tiles::Tile tile_2_reference{2308259840, 1407668224, 32};
|
|
||||||
tiles::Tile tile_3_reference{616562688, 2805989376, 32};
|
|
||||||
tiles::Tile tile_4_reference{1417674752, 2084569088, 32};
|
|
||||||
tiles::Tile tile_5_reference{616562688, 2805989376, 32};
|
|
||||||
tiles::Tile tile_6_reference{712654285, 2671662374, 32};
|
|
||||||
|
|
||||||
auto tile_1 =
|
|
||||||
tiles::pointToTile(FloatLongitude(13.31817626953125), FloatLatitude(52.449314140869696));
|
|
||||||
auto tile_2 =
|
|
||||||
tiles::pointToTile(FloatLongitude(13.476104736328125), FloatLatitude(52.56529070208021));
|
|
||||||
auto tile_3 =
|
|
||||||
tiles::pointToTile(FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186));
|
|
||||||
auto tile_4 =
|
|
||||||
tiles::pointToTile(FloatLongitude(-61.17187499999999), FloatLatitude(5.266007882805498));
|
|
||||||
auto tile_5 =
|
|
||||||
tiles::pointToTile(FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186));
|
|
||||||
auto tile_6 =
|
|
||||||
tiles::pointToTile(FloatLongitude(-120.266007882805532), FloatLatitude(-40.17187499999999));
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.x, tile_1_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.y, tile_1_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.z, tile_1_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.x, tile_2_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.y, tile_2_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.z, tile_2_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.x, tile_3_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.y, tile_3_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.z, tile_3_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_4.x, tile_4_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_4.y, tile_4_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_4.z, tile_4_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_5.x, tile_5_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_5.y, tile_5_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_5.z, tile_5_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_6.x, tile_6_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_6.y, tile_6_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_6.z, tile_6_reference.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the bearing-bounds checking function behaves as expected
|
|
||||||
BOOST_AUTO_TEST_CASE(bounding_box_to_tile_test)
|
|
||||||
{
|
|
||||||
tiles::Tile tile_1_reference{17, 10, 5};
|
|
||||||
tiles::Tile tile_2_reference{0, 0, 0};
|
|
||||||
tiles::Tile tile_3_reference{0, 2, 2};
|
|
||||||
auto tile_1 = tiles::getBBMaxZoomTile(
|
|
||||||
FloatLongitude(13.31817626953125), FloatLatitude(52.449314140869696),
|
|
||||||
FloatLongitude(13.476104736328125), FloatLatitude(52.56529070208021));
|
|
||||||
auto tile_2 = tiles::getBBMaxZoomTile(
|
|
||||||
FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186),
|
|
||||||
FloatLongitude(-61.17187499999999), FloatLatitude(5.266007882805498));
|
|
||||||
auto tile_3 = tiles::getBBMaxZoomTile(
|
|
||||||
FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186),
|
|
||||||
FloatLongitude(-120.2660078828055), FloatLatitude(-40.17187499999999));
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.x, tile_1_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.y, tile_1_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_1.z, tile_1_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.x, tile_2_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.y, tile_2_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_2.z, tile_2_reference.z);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.x, tile_3_reference.x);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.y, tile_3_reference.y);
|
|
||||||
BOOST_CHECK_EQUAL(tile_3.z, tile_3_reference.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#include "util/viewport.hpp"
|
||||||
|
|
||||||
|
using namespace osrm::util;
|
||||||
|
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <boost/test/test_case_template.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(viewport_test)
|
||||||
|
|
||||||
|
using namespace osrm;
|
||||||
|
using namespace osrm::util;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(zoom_level_test)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL(
|
||||||
|
viewport::getFittedZoom(
|
||||||
|
Coordinate(FloatLongitude{5.668343999999995}, FloatLatitude{45.111511000000014}),
|
||||||
|
Coordinate(FloatLongitude{5.852471999999996}, FloatLatitude{45.26800200000002})),
|
||||||
|
12);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
Reference in New Issue
Block a user