Compare commits

..

135 Commits

Author SHA1 Message Date
Patrick Niklaus a558e5de4f Fix shared memory 2016-03-18 14:05:46 +01:00
Patrick Niklaus d62f8bc994 Fixup for last commit 2016-03-17 23:01:56 +01:00
Daniel Patterson f11dc9b978 Enables the use of multiple segment-speed-files on the osrm-contract
command line, and exposes the file name used for each edge in the debug
tiles.
2016-03-17 22:59:52 +01:00
Patrick Niklaus 93a05b7f70 Fix ingestion fixed duration values from UnpackPath 2016-03-17 22:59:52 +01:00
Patrick Niklaus 9b75ff98c9 Fix durations in UnpackPath 2016-03-17 22:59:51 +01:00
Moritz Kobitzsch b28d1a00d6 fixes a broken assertion 2016-03-17 22:57:42 +01:00
Moritz Kobitzsch 8ddbbb0889 fix merging of turn instructions 2016-03-17 22:57:42 +01:00
Patrick Niklaus 8345648c02 Include reverse edges again 2016-03-17 22:57:42 +01:00
Patrick Niklaus 15fa82405b Formating and logging changes for turn classification 2016-03-17 22:57:42 +01:00
Patrick Niklaus e53e1cbe0f Handle case of dead-end edges by inserting an invalid turn 2016-03-17 22:57:42 +01:00
Moritz Kobitzsch a48e5e4804 report depart/arrive in addition to waypoint 2016-03-17 22:57:42 +01:00
Patrick Niklaus 9519ff2e30 Only install necessary headers 2016-03-17 22:57:42 +01:00
Daniel J. Hofmann 7543de4480 Adds the license preamble for all publicly installed eaders, closes #2036 2016-03-17 22:57:42 +01:00
Patrick Niklaus 93e8c42589 Remove the encoder/decoder dependecy from Hint 2016-03-17 22:57:42 +01:00
Patrick Niklaus 9e140d1e0f Rename alternative -> alternatives 2016-03-17 22:57:42 +01:00
Patrick Niklaus bf73834a72 Remove obsolete debug information 2016-03-17 22:57:42 +01:00
Patrick Niklaus b637fffc01 Just return NoSegment in map matching if all candidates are empty 2016-03-17 22:57:41 +01:00
Patrick Niklaus f31617dd9c Add failing test for map matching of outlier 2016-03-17 22:57:41 +01:00
Patrick Niklaus 28ed237f9a Fix missing capitalization of error codes 2016-03-17 22:57:41 +01:00
Moritz Kobitzsch 973785d1eb encapsulated into class 2016-03-17 22:57:41 +01:00
Moritz Kobitzsch b04919db51 improving fork handling on three-way turns 2016-03-17 22:57:41 +01:00
Moritz Kobitzsch 0ccce27fdf fix comparison for ramps on three-way turns 2016-03-17 22:57:41 +01:00
Patrick Niklaus 5e82ee60e7 Minor auto iterator cleanup 2016-03-17 22:57:41 +01:00
Patrick Niklaus 05f1c85de3 Don't pass down unsnapped coordinates. All information is already there 2016-03-17 22:57:41 +01:00
Patrick Niklaus aca943723f Fix camMergeTrivially 2016-03-17 22:57:41 +01:00
Moritz Kobitzsch d82d7cf66e fixes roundabout counting 2016-03-17 22:57:41 +01:00
Moritz Kobitzsch c608b77a43 fixes assignment for basic turn types / invalid ramp assignment 2016-03-17 22:57:41 +01:00
Patrick Niklaus 07dba1c325 Add edge id assertions 2016-03-17 22:57:41 +01:00
Patrick Niklaus f06a636e7d Don't pass shared_ptr down to functions
"Don’t pass a smart pointer as a function parameter unless you want to
use or manipulate the smart pointer itself, such as to share or transfer
ownership."

Source:
http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
2016-03-17 22:57:41 +01:00
Patrick Niklaus 3060f4414d Move bearing to public namespace 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann bf01038e63 Properly includes needed headers in turn analysis interface 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann c6004d4401 Const-correctnes for compressed geometry iterator 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann d8759b7a2e Use stdint and using type-alias for discrete angle 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann 304f361077 Hide functional road classification based on tags in implementation file 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann aeb435a2f7 Inline initialize functional road classification hash table 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann fca25b45cd 256 functional road classes should be enough 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann 2402a1341a Moves route assembly into implementation file 2016-03-17 22:57:41 +01:00
Daniel J. Hofmann c9a0c0da1c Fixes remaining engine/guidance includes 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 9c5d0f1e91 Fixes accumulate living in <numeric> and not <algorithm> 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann f47f008e7d Puts step maneuver handling into implementation file 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 1fe9012c29 Removes penalizing move 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 9db0b029aa Uses static_casts for underlying type in post processing 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann c48e5f5ee2 Fix asymmetry in min/max from using -max 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 5eb8990739 Adapts MakeResponse to not pass vector by pointer 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 533d6c0a6b Fixes multi-line comment 2016-03-17 22:57:40 +01:00
Daniel J. Hofmann 2a454c4272 Runs scripts/format.sh 2016-03-17 22:57:40 +01:00
Patrick Niklaus 908fd98824 Fix coodinate include and unused warnings 2016-03-17 22:57:40 +01:00
Moritz Kobitzsch 4f0a84e8de start of four way turns 2016-03-17 22:57:40 +01:00
Moritz Kobitzsch 6883fdca5c improved fork handling 2016-03-17 22:57:40 +01:00
Patrick Niklaus 396e14d46e Fix crash on extracting Berlin in guidance 2016-03-17 22:57:40 +01:00
Moritz Kobitzsch 951ffe8484 bugfixing/classification 2016-03-17 22:57:39 +01:00
Patrick Niklaus 6aa12b1dd6 Big Restructuring / Cleanup 2016-03-17 22:53:43 +01:00
Moritz Kobitzsch 74fe0beef6 starting on conflict resolution 2016-03-17 22:50:44 +01:00
Lauren Budorick 383c9619ec Fixes for gcc compiling, temporary hacks to remove later 2016-03-17 22:50:44 +01:00
Moritz Kobitzsch b85270e540 handle segregated roads (merge for turn analysis) 2016-03-17 22:50:42 +01:00
Moritz Kobitzsch b06dddaf5e structural changes, motorway handling 2016-03-17 22:49:02 +01:00
Moritz Kobitzsch 3fa9672d9a enter and exit roundabout feature - currently not showing turn 2016-03-17 22:46:22 +01:00
Moritz Kobitzsch 6547978906 migrated out of edge based graph factory 2016-03-17 22:46:21 +01:00
Moritz Kobitzsch 9087a01aac relative waypoint locations 2016-03-17 22:38:00 +01:00
Moritz Kobitzsch ad56ed8832 handling of roundabouts (simple version) 2016-03-17 22:38:00 +01:00
Moritz Kobitzsch 4b46dec169 advanced guidance on 5.0 2016-03-17 22:37:58 +01:00
Patrick Niklaus 6f5c3067f1 Fix numerical problems with polyline 2016-03-17 22:15:13 +01:00
Patrick Niklaus 41600eeadc Fix table response format to return null + double in seconds 2016-03-17 22:15:13 +01:00
Patrick Niklaus 6dd23b2984 Return NoMatch 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann 91b97ae7f7 Provides ctor from base path for EngineConfig, fixes #2030 2016-03-17 22:15:13 +01:00
Patrick Niklaus 28de928a5d Add support for tile plugin 2016-03-17 22:15:13 +01:00
Patrick Niklaus 209d1ada6a Preliminary integration of the tile plugin 2016-03-17 22:15:13 +01:00
Patrick Niklaus 399a2233f3 sources and destinations can be empty actually 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann d4009e11d5 Fixes coordinate, source and destination validation by means of backporting #2041 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann 8c9100cd9e Fixes ownership semantics and forwarding references misplacements in the JSON factory 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann 3a7d527a7e Unwrap function call from identity lambda 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann c96a485108 Uses JSON's String constructor for polyline encoding 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann c2de49ccab Passes coordinates by value 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann ae8dde6afe Asserts on unknown TurnInstruction 2016-03-17 22:15:13 +01:00
Daniel J. Hofmann 6bc3f5d6da Fixes header includes in the JSON factory 2016-03-17 22:15:13 +01:00
Dane Springmeyer dbab7b421c fix compile of osrm-components 2016-03-17 22:15:13 +01:00
Patrick Niklaus 4dd6dfbfe2 Fix if the last coordinate is not found 2016-03-17 22:15:13 +01:00
Patrick Niklaus f039da95ec Allocate correct table size 2016-03-17 22:15:13 +01:00
Patrick Niklaus 5626182c60 Fix travel mode passing from profiles up to the API 2016-03-17 22:15:13 +01:00
Patrick Niklaus 721cc32acb Fix geometries type in steps 2016-03-17 22:15:13 +01:00
Patrick Niklaus 0ec5f06a2f Fix table parameter parsing 2016-03-17 22:15:13 +01:00
Patrick Niklaus 32982c7609 Fix behaviour of table if sources/destinations arrays are empty 2016-03-17 22:15:12 +01:00
Patrick Niklaus 828767ba18 Fuck. this. shit. 2016-03-17 22:15:12 +01:00
Patrick Niklaus 83deae637b Change stream operator of strong typedef 2016-03-17 22:15:12 +01:00
Patrick Niklaus 88f9cf5aea Fix stream operator for coordinate 2016-03-17 22:15:12 +01:00
Patrick Niklaus f5e79f5c7e Add stream operator to Rectangle 2016-03-17 22:15:12 +01:00
Patrick Niklaus 3f7056ee30 Add euclideanDistance to coordinate_calculation 2016-03-17 22:15:12 +01:00
Patrick Niklaus 0aa98454f5 Simplify static_rtree tests 2016-03-17 22:15:12 +01:00
Patrick Niklaus eb179af1ce First round of lat,lng -> lng,lat switcheroo 2016-03-17 22:15:10 +01:00
Patrick Niklaus 03a230a768 Add rectangle unit test 2016-03-17 21:57:36 +01:00
Patrick Niklaus 0bd658c304 Fix match and trip API response 2016-03-17 21:57:36 +01:00
Patrick Niklaus 0c8113943b Fix out-of-bounds write in map_matching 2016-03-17 21:57:36 +01:00
Dane Springmeyer ef790e8e82 Fix compile on OS X 2016-03-17 21:57:36 +01:00
Patrick Niklaus cd4dbfac42 Finish the nearest plugin 2016-03-17 21:57:36 +01:00
Patrick Niklaus 6b72c007f9 Initialize NearestParameters correctly 2016-03-17 21:57:36 +01:00
Patrick Niklaus 007e4a69c8 Adapt to feedback in #519 2016-03-17 21:57:36 +01:00
Patrick Niklaus fab343d0d3 Add trip plugin 2016-03-17 21:57:36 +01:00
Patrick Niklaus 8d4ee327cd Hook up map matching 2016-03-17 21:57:36 +01:00
Patrick Niklaus ba2feca497 First compiling version of map_match plugin 2016-03-17 21:57:36 +01:00
Daniel J. Hofmann a9872a4892 Adapts example/example.cpp to new osrm api 2016-03-17 21:57:36 +01:00
Daniel J. Hofmann 0369634886 Install _all_ transitively from public headers included header 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann b10bd7c45e Fix missing headers in hint.hpp 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 2134162fc6 Adds $prefix/include/osrm to include dirs so that transitive header includes without osrm prefix can be found 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 00b3147c9b Adapt the example to include all osrm public headers 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 3b6d6bbbf2 Fixes missing public header installations 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 52653c8ffa Fix forward declarations in publicly facing osrm header 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 891ac48d1c Enable all plugins with aStatus::Error return code fallback for not implemented ones 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 26dd3c8cd7 Adds publicly facing alias headers for parameters 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 820d0444fb Temporarily comment out match.cpp as to not break the build process 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann b1a11aa567 We don't need templates at all, this is not CRTP? 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 0c970e4035 Fix classes for service member function definitions 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann c21e0855e9 Service skeletons for nearest, trip, match 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 1b2bbd086e Fix grammar constraint and enable all plugin links 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 8eee4c23cc Plugin grammar skeletons 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 7e1c164937 Enforce parameter and grammar type to catch subtle bugs 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 6fecce23fc Link parameters to grammars 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 7abb7ed0e1 Require a BaseParameters type at compile time via enable_if 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 097771879b Adapts Nearest plugin to new API 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 2d558a0b83 Fix deleting incomplete type and make Engine moveable only 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 23a5edb29b Adapts publicly facing new API 2016-03-17 21:57:35 +01:00
Daniel J. Hofmann 942c71814d Adapts NearestParameters to new API 2016-03-17 21:57:34 +01:00
Patrick Niklaus 482aa63001 Initial non-building match plugin 2016-03-17 21:57:34 +01:00
Lauren Budorick 989bbfb250 Include numeric in assemble_overview.cpp (needed on OSX for std::accumulate) 2016-03-17 21:57:34 +01:00
Daniel J. Hofmann decf976489 Semantic action handler requires passing optional by value and fusion::vector2 2016-03-17 21:57:34 +01:00
Patrick Niklaus 88a501f77c Add tests for bearing parsing 2016-03-17 21:57:34 +01:00
Patrick Niklaus 98beea7649 Add table service 2016-03-17 21:57:34 +01:00
Patrick Niklaus 2bd8efd140 Add table API 2016-03-17 21:57:34 +01:00
Daniel J. Hofmann 73e71765ab Optional<T> semantic action handler takes T argument 2016-03-17 21:57:34 +01:00
Patrick Niklaus a57680323f Fix parameter parsing tests 2016-03-17 21:57:34 +01:00
Patrick Niklaus 75f356fcc6 Fix table plugin 2016-03-17 21:57:34 +01:00
Daniel J. Hofmann d35c862a8b First take at distance table API re-write 2016-03-17 21:57:34 +01:00
Daniel J. Hofmann df236b72fb Adapts TableParameters and its validation to new API 2016-03-17 21:57:34 +01:00
Patrick Niklaus 8b2b153465 Add viaroute suport for new API 2016-03-17 21:57:32 +01:00
Patrick Niklaus 26ffdf2dcb Also exclude the compressed flag from the data format 2016-03-17 17:23:36 +01:00
Patrick Niklaus 3377bf8faf Remove geometry indicator 2016-03-17 16:40:08 +01:00
93 changed files with 3109 additions and 4165 deletions
+2 -4
View File
@@ -80,7 +80,7 @@ add_executable(osrm-extract src/tools/extract.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-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<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_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
@@ -94,7 +94,6 @@ add_executable(server-tests EXCLUDE_FROM_ALL unit_tests/server_tests.cpp ${Serve
# Benchmarks
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(rtree-bench PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
@@ -382,10 +381,9 @@ 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(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(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 ${UtilHeader} DESTINATION include/osrm/util)
install(FILES ${StorageHeader} DESTINATION include/osrm/storage)
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
install(FILES ${LibraryGlob} DESTINATION include/osrm)
+1 -2
View File
@@ -29,8 +29,7 @@ int main(int argc, const char *argv[]) try
using namespace osrm;
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
EngineConfig config;
config.storage_config = {argv[1]};
EngineConfig config{argv[1]};
config.use_shared_memory = false;
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
-202
View File
@@ -1,202 +0,0 @@
@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 |
-173
View File
@@ -1,173 +0,0 @@
@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 |
+12 -12
View File
@@ -8,7 +8,6 @@
#include "engine/hint.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <vector>
@@ -34,23 +33,24 @@ class BaseAPI
util::json::Array waypoints;
waypoints.values.resize(parameters.coordinates.size());
waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
waypoints.values[0] = MakeWaypoint(parameters.coordinates.front(),
segment_end_coordinates.front().source_phantom);
auto coord_iter = std::next(parameters.coordinates.begin());
auto out_iter = std::next(waypoints.values.begin());
boost::range::transform(segment_end_coordinates, out_iter,
[this](const PhantomNodes &phantom_pair)
{
return MakeWaypoint(phantom_pair.target_phantom);
});
for (const auto &phantoms : segment_end_coordinates)
{
*out_iter++ = MakeWaypoint(*coord_iter++, phantoms.target_phantom);
}
return waypoints;
}
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
util::json::Object MakeWaypoint(const PhantomNode &phantom) const
protected:
util::json::Object MakeWaypoint(const util::Coordinate input_coordinate,
const PhantomNode &phantom) const
{
return json::makeWaypoint(phantom.location, facade.GetNameForID(phantom.name_id),
Hint{phantom, facade.GetCheckSum()});
return json::makeWaypoint(phantom.location, facade.get_name_for_id(phantom.name_id),
Hint{input_coordinate, phantom, facade.GetCheckSum()});
}
const datafacade::BaseDataFacade &facade;
+2 -4
View File
@@ -48,9 +48,7 @@ class MatchAPI final : public RouteAPI
response.values["code"] = "ok";
}
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
protected:
// FIXME this logic is a little backwards. We should change the output format of the
// map_matching
// routing algorithm to be easier to consume here.
@@ -100,7 +98,7 @@ class MatchAPI final : public RouteAPI
}
const auto &phantom =
sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index];
auto waypoint = BaseAPI::MakeWaypoint(phantom);
auto waypoint = BaseAPI::MakeWaypoint(parameters.coordinates[trace_index], phantom);
waypoint.values["matchings_index"] = matching_index.sub_matching_index;
waypoint.values["waypoint_index"] = matching_index.point_index;
waypoints.values.push_back(std::move(waypoint));
+2 -1
View File
@@ -38,7 +38,8 @@ class NearestAPI final : public BaseAPI
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance)
{
auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
auto waypoint = MakeWaypoint(parameters.coordinates.front(),
phantom_with_distance.phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance;
return waypoint;
});
+6 -34
View File
@@ -57,8 +57,7 @@ class RouteAPI : public BaseAPI
response.values["code"] = "ok";
}
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
protected:
template <typename ForwardIter>
util::json::Value MakeGeometry(ForwardIter begin, ForwardIter end) const
{
@@ -72,7 +71,7 @@ class RouteAPI : public BaseAPI
}
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
const std::vector<std::vector<PathData>> &unpacked_path_segments,
std::vector<std::vector<PathData>> unpacked_path_segments,
const std::vector<bool> &source_traversed_in_reverse,
const std::vector<bool> &target_traversed_in_reverse) const
{
@@ -82,6 +81,7 @@ class RouteAPI : public BaseAPI
legs.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))
{
const auto &phantoms = segment_end_coordinates[idx];
@@ -93,47 +93,19 @@ class RouteAPI : public BaseAPI
auto leg_geometry = guidance::assembleGeometry(
BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
auto leg = guidance::assembleLeg(BaseAPI::facade, path_data, leg_geometry,
phantoms.target_phantom, reversed_target);
phantoms.source_phantom, phantoms.target_phantom,
reversed_source, reversed_target);
if (parameters.steps)
{
auto steps = guidance::assembleSteps(
leg.steps = guidance::assembleSteps(
BaseAPI::facade, path_data, leg_geometry, phantoms.source_phantom,
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));
legs.push_back(std::move(leg));
}
auto route = guidance::assembleRoute(legs);
boost::optional<util::json::Value> json_overview;
if (parameters.overview != RouteParameters::OverviewType::False)
+5 -4
View File
@@ -60,10 +60,10 @@ struct RouteParameters : public BaseParameters
const bool alternatives_,
const GeometriesType geometries_,
const OverviewType overview_,
const boost::optional<bool> uturns_,
std::vector<boost::optional<bool>> uturns_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
geometries{geometries_}, overview{overview_}, uturns{uturns_}
geometries{geometries_}, overview{overview_}, uturns{std::move(uturns_)}
{
}
@@ -71,11 +71,12 @@ struct RouteParameters : public BaseParameters
bool alternatives = true;
GeometriesType geometries = GeometriesType::Polyline;
OverviewType overview = OverviewType::Simplified;
boost::optional<bool> uturns;
std::vector<boost::optional<bool>> uturns;
bool IsValid() const
{
return coordinates.size() >= 2 && BaseParameters::IsValid();
return coordinates.size() >= 2 && BaseParameters::IsValid() &&
(uturns.empty() || uturns.size() == coordinates.size());
}
};
}
+14 -16
View File
@@ -17,8 +17,6 @@
#include "util/integer_range.hpp"
#include <boost/range/algorithm/transform.hpp>
namespace osrm
{
namespace engine
@@ -68,19 +66,19 @@ class TableAPI final : public BaseAPI
response.values["code"] = "ok";
}
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
protected:
virtual util::json::Array MakeWaypoints(const std::vector<PhantomNode> &phantoms) const
{
util::json::Array json_waypoints;
json_waypoints.values.reserve(phantoms.size());
BOOST_ASSERT(phantoms.size() == parameters.coordinates.size());
boost::range::transform(phantoms, std::back_inserter(json_waypoints.values),
[this](const PhantomNode &phantom)
{
return BaseAPI::MakeWaypoint(phantom);
});
auto phantom_iter = phantoms.begin();
auto coordinate_iter = parameters.coordinates.begin();
for (; phantom_iter != phantoms.end() && coordinate_iter != parameters.coordinates.end();
++phantom_iter, ++coordinate_iter)
{
json_waypoints.values.push_back(BaseAPI::MakeWaypoint(*coordinate_iter, *phantom_iter));
}
return json_waypoints;
}
@@ -89,12 +87,12 @@ class TableAPI final : public BaseAPI
{
util::json::Array json_waypoints;
json_waypoints.values.reserve(indices.size());
boost::range::transform(indices, std::back_inserter(json_waypoints.values),
[this, phantoms](const std::size_t idx)
{
BOOST_ASSERT(idx < phantoms.size());
return BaseAPI::MakeWaypoint(phantoms[idx]);
});
for (auto idx : indices)
{
BOOST_ASSERT(idx < phantoms.size() && idx < parameters.coordinates.size());
json_waypoints.values.push_back(
BaseAPI::MakeWaypoint(parameters.coordinates[idx], phantoms[idx]));
}
return json_waypoints;
}
+7 -8
View File
@@ -36,10 +36,10 @@ class TripAPI final : public RouteAPI
BOOST_ASSERT(sub_trips.size() == sub_routes.size());
for (auto index : util::irange<std::size_t>(0UL, sub_trips.size()))
{
auto route = MakeRoute(sub_routes[index].segment_end_coordinates,
sub_routes[index].unpacked_path_segments,
sub_routes[index].source_traversed_in_reverse,
sub_routes[index].target_traversed_in_reverse);
auto route = MakeRoute(
sub_routes[index].segment_end_coordinates, sub_routes[index].unpacked_path_segments,
sub_routes[index].source_traversed_in_reverse,
sub_routes[index].target_traversed_in_reverse);
routes.values.push_back(std::move(route));
}
response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms);
@@ -47,9 +47,7 @@ class TripAPI final : public RouteAPI
response.values["code"] = "ok";
}
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
protected:
// 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.
util::json::Array MakeWaypoints(const std::vector<std::vector<NodeID>> &sub_trips,
@@ -92,7 +90,8 @@ class TripAPI final : public RouteAPI
auto trip_index = input_idx_to_trip_idx[input_index];
BOOST_ASSERT(!trip_index.NotUsed());
auto waypoint = BaseAPI::MakeWaypoint(phantoms[input_index]);
auto waypoint =
BaseAPI::MakeWaypoint(parameters.coordinates[input_index], phantoms[input_index]);
waypoint.values["trips_index"] = trip_index.sub_trip_index;
waypoint.values["waypoint_index"] = trip_index.point_index;
waypoints.values.push_back(std::move(waypoint));
-126
View File
@@ -1,126 +0,0 @@
#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,13 +138,11 @@ class BaseDataFacade
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
virtual std::string GetNameForID(const unsigned name_id) const = 0;
virtual std::string get_name_for_id(const unsigned name_id) const = 0;
virtual std::size_t GetCoreSize() const = 0;
virtual std::string GetTimestamp() const = 0;
virtual bool GetUTurnsDefault() const = 0;
};
}
}
@@ -9,7 +9,6 @@
#include "engine/geospatial_query.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "contractor/query_edge.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
@@ -80,7 +79,6 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<unsigned, false>::vector m_segment_weights;
util::ShM<uint8_t, false>::vector m_datasource_list;
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<InternalGeospatialQuery> m_geospatial_query;
@@ -88,26 +86,26 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::path file_index_path;
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 &timestamp_path)
{
util::SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestamp_stream(timestamp_path);
if (!timestamp_stream)
if (boost::filesystem::exists(timestamp_path))
{
throw util::exception("Could not open " + timestamp_path.string() + " for reading.");
util::SimpleLogger().Write() << "Loading Timestamp";
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)
@@ -220,33 +218,28 @@ class InternalDataFacade final : public BaseDataFacade
void LoadDatasourceInfo(const boost::filesystem::path &datasource_names_file,
const boost::filesystem::path &datasource_indexes_file)
{
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
if (!datasources_stream)
std::ifstream datasources_stream(datasource_indexes_file.c_str(), std::ios::binary);
if (datasources_stream)
{
throw util::exception("Could not open " + datasource_indexes_file.string() + " for reading!");
}
BOOST_ASSERT(datasources_stream);
std::size_t number_of_datasources = 0;
datasources_stream.read(reinterpret_cast<char *>(&number_of_datasources),
sizeof(std::size_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::size_t number_of_datasources = 0;
datasources_stream.read(reinterpret_cast<char *>(&number_of_datasources),
sizeof(std::size_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));
}
}
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
if (!datasourcenames_stream)
std::ifstream datasourcenames_stream(datasource_names_file.c_str(), std::ios::binary);
if (datasourcenames_stream)
{
throw util::exception("Could not open " + datasource_names_file.string() + " for reading!");
}
BOOST_ASSERT(datasourcenames_stream);
std::string name;
while (std::getline(datasourcenames_stream, name))
{
m_datasource_names.push_back(std::move(name));
std::string name;
while (std::getline(datasourcenames_stream, name))
{
m_datasource_names.push_back(name);
}
}
}
@@ -283,35 +276,52 @@ class InternalDataFacade final : public BaseDataFacade
m_geospatial_query.reset();
}
explicit InternalDataFacade(const storage::StorageConfig& config)
explicit InternalDataFacade(
const std::unordered_map<std::string, boost::filesystem::path> &server_paths)
{
ram_index_path = config.ram_index_path;
file_index_path = config.file_index_path;
// cache end iterator to quickly check .find against
const auto end_it = end(server_paths);
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";
LoadGraph(config.hsgr_data_path);
LoadGraph(file_for("hsgrdata"));
util::SimpleLogger().Write() << "loading edge information";
LoadNodeAndEdgeInformation(config.nodes_data_path, config.edges_data_path);
LoadNodeAndEdgeInformation(file_for("nodesdata"), file_for("edgesdata"));
util::SimpleLogger().Write() << "loading core information";
LoadCoreInformation(config.core_data_path);
LoadCoreInformation(file_for("coredata"));
util::SimpleLogger().Write() << "loading geometries";
LoadGeometries(config.geometries_path);
LoadGeometries(file_for("geometries"));
util::SimpleLogger().Write() << "loading datasource info";
LoadDatasourceInfo(config.datasource_names_path,
config.datasource_indexes_path);
LoadDatasourceInfo(optional_file_for("datasource_names"),
optional_file_for("datasource_indexes"));
util::SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(config.timestamp_path);
util::SimpleLogger().Write() << "loading profile properties";
LoadProfileProperties(config.properties_path);
LoadTimestamp(file_for("timestamp"));
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
LoadStreetNames(file_for("namesdata"));
}
// search graph access
@@ -541,7 +551,7 @@ class InternalDataFacade final : public BaseDataFacade
return m_name_ID_list.at(id);
}
std::string GetNameForID(const unsigned name_id) const override final
std::string get_name_for_id(const unsigned name_id) const override final
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
@@ -642,14 +652,16 @@ class InternalDataFacade final : public BaseDataFacade
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
{
BOOST_ASSERT(m_datasource_names.size() >= 1);
BOOST_ASSERT(m_datasource_names.size() > datasource_name_id);
if (m_datasource_names.empty() || datasource_name_id > m_datasource_names.size())
{
if (datasource_name_id == 0)
return "lua profile";
return "UNKNOWN";
}
return m_datasource_names[datasource_name_id];
}
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetUTurnsDefault() const override final { return m_profile_properties.allow_u_turn_at_via; }
};
}
}
+10 -16
View File
@@ -8,7 +8,6 @@
#include "storage/shared_memory.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/profile_properties.hpp"
#include "engine/geospatial_query.hpp"
#include "util/range_table.hpp"
@@ -69,7 +68,6 @@ class SharedDataFacade final : public BaseDataFacade
std::unique_ptr<storage::SharedMemory> m_layout_memory;
std::unique_ptr<storage::SharedMemory> m_large_memory;
std::string m_timestamp;
extractor::ProfileProperties* m_profile_properties;
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
util::ShM<NodeID, true>::vector m_via_node_list;
@@ -100,12 +98,6 @@ class SharedDataFacade final : public BaseDataFacade
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()
{
auto timestamp_ptr =
@@ -351,7 +343,6 @@ class SharedDataFacade final : public BaseDataFacade
LoadViaNodeList();
LoadNames();
LoadCoreInformation();
LoadProfileProperties();
util::SimpleLogger().Write() << "number of geometries: "
<< m_coordinate_list->size();
@@ -630,7 +621,7 @@ class SharedDataFacade final : public BaseDataFacade
return m_name_ID_list.at(id);
}
std::string GetNameForID(const unsigned name_id) const override final
std::string get_name_for_id(const unsigned name_id) const override final
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
@@ -693,11 +684,16 @@ class SharedDataFacade final : public BaseDataFacade
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;
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],
m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id] +
m_datasource_name_lengths[datasource_name_id],
@@ -707,8 +703,6 @@ class SharedDataFacade final : public BaseDataFacade
}
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetUTurnsDefault() const override final { return m_profile_properties->allow_u_turn_at_via; }
};
}
}
+18 -4
View File
@@ -28,10 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ENGINE_CONFIG_HPP
#define ENGINE_CONFIG_HPP
#include "storage/storage_config.hpp"
#include <boost/filesystem/path.hpp>
#include <unordered_map>
#include <string>
namespace osrm
@@ -42,9 +41,24 @@ namespace engine
struct EngineConfig
{
bool IsValid() const;
EngineConfig() = default;
storage::StorageConfig storage_config;
EngineConfig(const boost::filesystem::path &base)
: 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_viaroute = -1;
int max_locations_distance_table = -1;
+8 -12
View File
@@ -244,8 +244,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, &has_big_component, &has_small_component](
const EdgeData &data)
[this, bearing, bearing_range, &has_big_component,
&has_small_component](const EdgeData &data)
{
auto use_segment =
(!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;
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, &has_big_component, &has_small_component](
const EdgeData &data)
[this, bearing, bearing_range, &has_big_component,
&has_small_component](const EdgeData &data)
{
auto use_segment =
(!has_small_component || (!has_big_component && !data.component.is_tiny));
@@ -393,14 +393,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_weight *= 1.0 - ratio;
}
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
forward_weight,
forward_offset,
reverse_weight,
reverse_offset,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
auto transformed =
PhantomNodeWithDistance{PhantomNode{data, forward_weight, forward_offset,
reverse_weight, reverse_offset, point_on_segment},
current_perpendicular_distance};
return transformed;
}
@@ -51,8 +51,7 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
current_distance +=
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
// all changes to this check have to be matched with assemble_steps
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
if (!isSilent(path_point.turn_instruction))
{
geometry.segment_distances.push_back(current_distance);
geometry.segment_offsets.push_back(geometry.locations.size());
+17 -7
View File
@@ -96,12 +96,18 @@ template <typename DataFacadeT>
RouteLeg assembleLeg(const DataFacadeT &facade,
const std::vector<PathData> &route_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool source_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 =
(target_traversed_in_reverse ? target_node.reverse_weight
: target_node.forward_weight) /
(target_traversed_in_reverse ? target_node.GetReverseWeightPlusOffset()
: target_node.GetForwardWeightPlusOffset()) /
10.;
auto distance = std::accumulate(leg_geometry.segment_distances.begin(),
@@ -130,21 +136,25 @@ RouteLeg assembleLeg(const DataFacadeT &facade,
// The phantom node of t will contain:
// `forward_weight`: duration of (d,t)
// `forward_offset`: duration of (c, d)
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
// caputed by the phantom node. So we need to add the target duration here.
duration = duration + target_duration;
//
// TODO discuss, this should not be the case after danpats fixes
// The PathData will contain entries of b, c and d. But only c will contain
// 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);
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
BOOST_ASSERT(summary_array.begin() != summary_array.end());
std::string summary =
std::accumulate(std::next(summary_array.begin()), summary_array.end(),
facade.GetNameForID(summary_array.front()),
facade.get_name_for_id(summary_array.front()),
[&facade](std::string previous, const std::uint32_t name_id)
{
if (name_id != 0)
{
previous += ", " + facade.GetNameForID(name_id);
previous += ", " + facade.get_name_for_id(name_id);
}
return previous;
});
+33 -65
View File
@@ -24,14 +24,11 @@ namespace guidance
{
namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const LegGeometry &leg_geometry,
const std::size_t segment_index);
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 unsigned exit);
} // ns detail
template <typename DataFacadeT>
@@ -43,14 +40,13 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const bool source_traversed_in_reverse,
const bool target_traversed_in_reverse)
{
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.;
const EdgeWeight source_duration =
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
source_traversed_in_reverse ? source_node.forward_weight : source_node.reverse_weight;
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
: source_node.forward_travel_mode;
const EdgeWeight target_duration =
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
target_traversed_in_reverse ? target_node.forward_weight : target_node.reverse_weight;
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
: target_node.forward_travel_mode;
@@ -60,18 +56,10 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
steps.reserve(number_of_segments);
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 =
distance_to_start >= MINIMAL_RELATIVE_DISTANCE &&
distance_to_start <= MAXIMAL_RELATIVE_DISTANCE
leg_geometry.locations.size() >= 3
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
source_node.input_location, leg_geometry.locations[0], leg_geometry.locations[1]))
leg_geometry.locations[0], leg_geometry.locations[1], leg_geometry.locations[2]))
: extractor::guidance::DirectionModifier::UTurn;
if (leg_data.size() > 0)
@@ -80,8 +68,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry);
maneuver.location = source_node.location;
WaypointType::Depart, leg_geometry, segment_index, INVALID_EXIT_NR);
// PathData saves the information we need of the segment _before_ the turn,
// but a RouteStep is with regard to the segment after the turn.
@@ -92,22 +79,18 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
{
segment_duration += path_point.duration_until_turn;
// all changes to this check have to be matched with assemble_geometry
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
if (path_point.turn_instruction != extractor::guidance::TurnInstruction::NO_TURN())
{
BOOST_ASSERT(segment_duration >= 0);
const auto name = facade.GetNameForID(path_point.name_id);
const auto name = facade.get_name_for_id(path_point.name_id);
const auto distance = leg_geometry.segment_distances[segment_index];
steps.push_back(RouteStep{path_point.name_id,
name,
segment_duration / 10.0,
distance,
path_point.travel_mode,
maneuver,
steps.push_back(RouteStep{path_point.name_id, name, segment_duration / 10.0,
distance, path_point.travel_mode, maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
leg_geometry, segment_index);
WaypointType::None, leg_geometry,
segment_index, path_point.exit);
segment_index++;
segment_duration = 0;
}
@@ -115,12 +98,8 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const auto distance = leg_geometry.segment_distances[segment_index];
const int duration = segment_duration + target_duration;
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id),
duration / 10.,
distance,
target_mode,
maneuver,
steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id),
duration / 10., distance, target_mode, maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
}
@@ -133,46 +112,35 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |---| source_duration
// |---------| target_duration
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry);
StepManeuver maneuver = {source_node.location, 0., 0.,
extractor::guidance::TurnInstruction{
extractor::guidance::TurnType::NoTurn, initial_modifier},
WaypointType::Depart, INVALID_EXIT_NR};
int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{source_node.name_id,
facade.GetNameForID(source_node.name_id),
duration / 10.,
leg_geometry.segment_distances[segment_index],
source_mode,
std::move(maneuver),
leg_geometry.FrontIndex(segment_index),
steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id),
duration / 10., leg_geometry.segment_distances[segment_index], source_mode,
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 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 =
distance_from_end >= MINIMAL_RELATIVE_DISTANCE &&
distance_from_end <= MAXIMAL_RELATIVE_DISTANCE
leg_geometry.locations.size() >= 3
? 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() - 1],
target_node.input_location))
leg_geometry.locations[leg_geometry.locations.size() - 1]))
: extractor::guidance::DirectionModifier::UTurn;
// This step has length zero, the only reason we need it is the target location
auto final_maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn, final_modifier},
WaypointType::Arrive, leg_geometry);
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id),
ZERO_DURATION,
ZERO_DISTANCE,
target_mode,
final_maneuver,
leg_geometry.locations.size(),
leg_geometry.locations.size()});
steps.push_back(RouteStep{
target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode,
StepManeuver{target_node.location, 0., 0.,
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
final_modifier},
WaypointType::Arrive, INVALID_EXIT_NR},
leg_geometry.locations.size(), leg_geometry.locations.size()});
return steps;
}
+2 -11
View File
@@ -1,8 +1,7 @@
#ifndef ENGINE_GUIDANCE_POST_PROCESSING_HPP
#define ENGINE_GUIDANCE_POST_PROCESSING_HPP
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/internal_route_result.hpp"
#include <vector>
@@ -13,15 +12,7 @@ namespace engine
namespace guidance
{
// 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);
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> path_data);
} // namespace guidance
} // namespace engine
-10
View File
@@ -5,7 +5,6 @@
#include "extractor/guidance/turn_instruction.hpp"
#include <cstdint>
#include <vector>
namespace osrm
{
@@ -21,14 +20,6 @@ enum class WaypointType : std::uint8_t
Depart,
};
//A represenetation of intermediate intersections
struct IntermediateIntersection
{
double duration;
double distance;
util::Coordinate location;
};
struct StepManeuver
{
util::Coordinate location;
@@ -37,7 +28,6 @@ struct StepManeuver
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
std::vector<IntermediateIntersection> intersections;
};
} // namespace guidance
} // namespace engine
+10 -15
View File
@@ -34,44 +34,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <cstdint>
#include <iosfwd>
namespace osrm
{
namespace engine
{
// Fwd. decls.
namespace datafacade
{
struct BaseDataFacade;
}
// Is returned as a temporary identifier for snapped coodinates
struct Hint
{
util::Coordinate input_coordinate;
PhantomNode phantom;
std::uint32_t data_checksum;
bool IsValid(const util::Coordinate new_input_coordinates,
const datafacade::BaseDataFacade &facade) const;
template <typename DataFacadeT>
bool IsValid(const util::Coordinate new_input_coordinates, DataFacadeT &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;
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
static_assert(sizeof(Hint) == 60 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 88;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
#else
// PhantomNode is bigger under windows because MSVC does not support bit packing
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 92;
constexpr std::size_t ENCODED_HINT_SIZE = 84;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
#endif
+2
View File
@@ -29,6 +29,8 @@ struct PathData
extractor::guidance::TurnInstruction turn_instruction;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// exit ID of highway exit, roundabout exit, intersection nr
unsigned exit;
};
struct InternalRouteResult
+91
View File
@@ -0,0 +1,91 @@
#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 */
+5 -16
View File
@@ -56,7 +56,6 @@ struct PhantomNode
bool is_tiny_component,
unsigned component_id,
util::Coordinate location,
util::Coordinate input_location,
unsigned short fwd_segment_position,
extractor::TravelMode forward_travel_mode,
extractor::TravelMode backward_travel_mode)
@@ -66,8 +65,8 @@ struct PhantomNode
forward_packed_geometry_id(forward_packed_geometry_id_),
reverse_packed_geometry_id(reverse_packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)),
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{
}
@@ -116,11 +115,6 @@ struct PhantomNode
(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 operator==(const PhantomNode &other) const { return location == other.location; }
@@ -131,8 +125,7 @@ struct PhantomNode
int forward_offset_,
int reverse_weight_,
int reverse_offset_,
const util::Coordinate location_,
const util::Coordinate input_location_)
const util::Coordinate foot_point)
{
forward_node_id = other.forward_edge_based_node_id;
reverse_node_id = other.reverse_edge_based_node_id;
@@ -150,8 +143,7 @@ struct PhantomNode
component.id = other.component.id;
component.is_tiny = other.component.is_tiny;
location = location_;
input_location = input_location_;
location = foot_point;
fwd_segment_position = other.fwd_segment_position;
forward_travel_mode = other.forward_travel_mode;
@@ -177,7 +169,6 @@ struct PhantomNode
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big");
#endif
util::Coordinate location;
util::Coordinate input_location;
unsigned short fwd_segment_position;
// note 4 bits would suffice for each,
// but the saved byte would be padding anyway
@@ -186,9 +177,7 @@ struct PhantomNode
};
#ifndef _MSC_VER
static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected");
#else
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
static_assert(sizeof(PhantomNode) == 52, "PhantomNode has more padding then expected");
#endif
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
+1
View File
@@ -5,6 +5,7 @@
#include "engine/plugins/plugin_base.hpp"
#include "engine/api/route_api.hpp"
#include "engine/object_encoder.hpp"
#include "engine/search_engine_data.hpp"
#include "engine/routing_algorithms/shortest_path.hpp"
#include "engine/routing_algorithms/alternative_path.hpp"
@@ -299,7 +299,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
weight_vector);
BOOST_ASSERT(weight_vector.size() > 0);
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
auto total_weight =
std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
BOOST_ASSERT(weight_vector.size() == id_vector.size());
// ed.distance should be total_weight + penalties (turn, stop, etc)
@@ -321,17 +322,14 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
{
unpacked_path.push_back(
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().duration_until_turn += (ed.distance - total_weight);
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:
// U---v---w---x---Z
// s
@@ -339,8 +337,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// However the first segment duration needs to be adjusted to the fact that the
// source phantom is in the middle of the segment.
// We do this by subtracting v--s from the duration.
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
unpacked_path.front().duration_until_turn -= source_weight;
BOOST_ASSERT(unpacked_path.front().duration_until_turn >=
phantom_node_pair.source_phantom.forward_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;
}
}
}
@@ -386,7 +388,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// s: fwd_segment 0
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
// note that (x, t) is _not_ included but needs to
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
{
BOOST_ASSERT(i < id_vector.size());
@@ -395,20 +397,20 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
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)
{
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).
// However the first segment duration needs to be adjusted to the fact that the source
// phantom is in the middle of the segment. We do this by subtracting v--s from the
// duration.
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
unpacked_path.front().duration_until_turn -= source_weight;
// phantom
// is in the middle of the segment. We do this by subtracting v--s from the duration.
BOOST_ASSERT(unpacked_path.front().duration_until_turn >=
phantom_node_pair.source_phantom.forward_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.
@@ -237,10 +237,14 @@ class ShortestPathRouting final
}
}
static const constexpr bool UTURN_DEFAULT = false;
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> uturns,
const std::vector<boost::optional<bool>> &uturn_indicators,
InternalRouteResult &raw_route_data) const
{
BOOST_ASSERT(uturn_indicators.empty() ||
uturn_indicators.size() == phantom_nodes_vector.size() + 1);
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
@@ -266,7 +270,7 @@ class ShortestPathRouting final
std::vector<NodeID> total_packed_path_to_reverse;
std::vector<std::size_t> packed_leg_to_reverse_begin;
const bool allow_u_turn_at_via = uturns ? *uturns : super::facade->GetUTurnsDefault();
const bool use_uturn_indicators = !uturn_indicators.empty();
std::size_t current_leg = 0;
// this implements a dynamic program that finds the shortest route through
@@ -282,6 +286,12 @@ class ShortestPathRouting final
const auto &source_phantom = phantom_node_pair.source_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_reverse_node = target_phantom.reverse_node_id != SPECIAL_NODEID;
@@ -4,7 +4,7 @@
#define EDGE_BASED_GRAPH_FACTORY_HPP_
#include "extractor/edge_based_edge.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/speed_profile.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_node.hpp"
@@ -17,7 +17,6 @@
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "util/deallocating_vector.hpp"
#include "util/name_table.hpp"
#include <algorithm>
#include <cstdint>
@@ -52,8 +51,7 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table);
SpeedProfileProperties speed_profile);
void Run(const std::string &original_edge_data_filename,
lua_State *lua_state,
@@ -106,9 +104,7 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &m_traffic_lights;
const CompressedEdgeContainer &m_compressed_edge_container;
ProfileProperties profile_properties;
const util::NameTable &name_table;
SpeedProfileProperties speed_profile;
void CompressGeometry();
unsigned RenumberEdges();
+2 -6
View File
@@ -40,8 +40,6 @@ namespace osrm
namespace extractor
{
struct ProfileProperties;
class Extractor
{
public:
@@ -51,15 +49,13 @@ class Extractor
private:
ExtractorConfig config;
void SetupScriptingEnvironment(lua_State *myLuaState, SpeedProfileProperties &speed_profile);
std::pair<std::size_t, std::size_t>
BuildEdgeExpandedGraph(lua_State* lua_state,
const ProfileProperties& profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
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 FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &edges,
-2
View File
@@ -71,7 +71,6 @@ struct ExtractorConfig
edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup";
edge_penalty_path = basepath + ".osrm.edge_penalties";
edge_based_node_weights_output_path = basepath + ".osrm.enw";
profile_properties_output_path = basepath + ".osrm.properties";
}
boost::filesystem::path config_file_path;
@@ -89,7 +88,6 @@ struct ExtractorConfig
std::string node_output_path;
std::string rtree_nodes_output_path;
std::string rtree_leafs_output_path;
std::string profile_properties_output_path;
unsigned requested_num_threads;
unsigned small_component_size;
+5
View File
@@ -3,6 +3,7 @@
#include "util/typedefs.hpp"
#include "extractor/speed_profile.hpp"
#include "util/node_based_graph.hpp"
#include <memory>
@@ -21,6 +22,8 @@ class GraphCompressor
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
public:
GraphCompressor(SpeedProfileProperties speed_profile);
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
RestrictionMap &restriction_map,
@@ -31,6 +34,8 @@ class GraphCompressor
void PrintStatistics(unsigned original_number_of_nodes,
unsigned original_number_of_edges,
const util::NodeBasedDynamicGraph &graph) const;
SpeedProfileProperties speed_profile;
};
}
}
+9 -91
View File
@@ -12,11 +12,9 @@
#include "extractor/guidance/classification_data.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <algorithm>
#include <map>
#include <cmath>
#include <cstdint>
#include <string>
namespace osrm
{
@@ -251,11 +249,10 @@ inline double angularDeviation(const double angle, const double from)
return std::min(360 - deviation, deviation);
}
inline double getAngularPenalty(const double angle, DirectionModifier modifier)
inline double getAngularPenalty(const double angle, TurnInstruction instruction)
{
// these are not aligned with getTurnDirection but represent an ideal center
const double center[] = {0, 45, 90, 135, 180, 225, 270, 315};
return angularDeviation(center[static_cast<int>(modifier)], angle);
return angularDeviation(center[static_cast<int>(instruction.direction_modifier)], angle);
}
inline double getTurnConfidence(const double angle, TurnInstruction instruction)
@@ -265,8 +262,8 @@ inline double getTurnConfidence(const double angle, TurnInstruction instruction)
if (!isBasic(instruction.type) || instruction.direction_modifier == DirectionModifier::UTurn)
return 1.0;
const double deviations[] = {0, 45, 50, 30, 20, 30, 50, 45};
const double difference = getAngularPenalty(angle, instruction.direction_modifier);
const double deviations[] = {0, 45, 50, 35, 10, 35, 50, 45};
const double difference = getAngularPenalty(angle, instruction);
const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)];
return 1.0 - (difference / max_deviation) * (difference / max_deviation);
}
@@ -284,7 +281,7 @@ inline DirectionModifier getTurnDirection(const double angle)
return DirectionModifier::Right;
if (angle >= 140 && angle < 170)
return DirectionModifier::SlightRight;
if (angle >= 165 && angle <= 195)
if (angle >= 170 && angle <= 190)
return DirectionModifier::Straight;
if (angle > 190 && angle <= 220)
return DirectionModifier::SlightLeft;
@@ -298,14 +295,10 @@ inline DirectionModifier getTurnDirection(const double angle)
// swaps left <-> right modifier types
inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier)
{
const constexpr DirectionModifier results[] = {DirectionModifier::UTurn,
DirectionModifier::SharpLeft,
DirectionModifier::Left,
DirectionModifier::SlightLeft,
DirectionModifier::Straight,
DirectionModifier::SlightRight,
DirectionModifier::Right,
DirectionModifier::SharpRight};
const constexpr DirectionModifier results[] = {
DirectionModifier::UTurn, DirectionModifier::SharpLeft, DirectionModifier::Left,
DirectionModifier::SlightLeft, DirectionModifier::Straight, DirectionModifier::SlightRight,
DirectionModifier::Right, DirectionModifier::SharpRight};
return results[modifier];
}
@@ -322,81 +315,6 @@ inline bool isLowPriorityRoadClass(const FunctionalRoadClass road_class)
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 extractor
} // namespace osrm
+93 -88
View File
@@ -6,14 +6,11 @@
#include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/name_table.hpp"
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include <utility>
#include <unordered_set>
namespace osrm
@@ -23,59 +20,42 @@ namespace extractor
namespace guidance
{
// What is exposed to the outside
struct TurnOperation final
struct TurnCandidate
{
EdgeID eid;
double angle;
TurnInstruction instruction;
};
// 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
EdgeID eid; // the id of the arc
bool valid; // a turn may be relevant to good instructions, even if we cannot take the road
double angle; // the approximated angle of the turn
TurnInstruction instruction; // a proposed instruction
double confidence; // how close to the border is the turn?
std::string toString() const
{
std::string result = "[connection] ";
result += std::to_string(turn.eid);
result += " allows entry: ";
result += std::to_string(entry_allowed);
std::string result = "[turn] ";
result += std::to_string(eid);
result += " valid: ";
result += std::to_string(valid);
result += " angle: ";
result += std::to_string(turn.angle);
result += std::to_string(angle);
result += " instruction: ";
result += std::to_string(static_cast<std::int32_t>(turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(turn.instruction.direction_modifier));
result += std::to_string(static_cast<std::int32_t>(instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(instruction.direction_modifier));
result += " confidence: ";
result += std::to_string(confidence);
return result;
}
};
class TurnAnalysis
{
public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table);
const CompressedEdgeContainer &compressed_edge_container);
// the entry into the turn analysis
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -83,14 +63,12 @@ class TurnAnalysis
const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes;
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
// from `from_node` via `via_eid`
// The resulting candidates have to be analysed for their actual instructions later on.
std::vector<ConnectedRoad> getConnectedRoads(const NodeID from_node,
std::vector<TurnCandidate> getTurnCandidates(const NodeID from_node,
const EdgeID via_eid) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
@@ -104,7 +82,10 @@ class TurnAnalysis
//
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
// 160
std::vector<ConnectedRoad> mergeSegregatedRoads(std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate>
mergeSegregatedRoads(const NodeID from_node,
const EdgeID via_eid,
std::vector<TurnCandidate> turn_candidates) const;
// TODO distinguish roundabouts and rotaries
// TODO handle bike/walk cases that allow crossing a roundabout!
@@ -112,86 +93,110 @@ class TurnAnalysis
// Processing of roundabouts
// Produces instructions to enter/exit a roundabout or to stay on it.
// Performs the distinction between roundabout and rotaries.
std::vector<ConnectedRoad> handleRoundabouts(const EdgeID via_edge,
std::vector<TurnCandidate> handleRoundabouts(const NodeID from,
const EdgeID via_edge,
const bool on_roundabout,
const bool can_enter_roundabout,
const bool can_exit_roundabout,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> turn_candidates) const;
// Indicates a Junction containing a motoryway
bool isMotorwayJunction(const EdgeID via_edge,
const std::vector<ConnectedRoad> &intersection) const;
bool isMotorwayJunction(const NodeID from,
const EdgeID via_edge,
const std::vector<TurnCandidate> &turn_candidates) const;
// Decide whether a turn is a turn or a ramp access
TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
TurnType findBasicTurnType(const EdgeID via_edge, const TurnCandidate &candidate) const;
// Get the Instruction for an obvious turn
// Instruction will be a silent instruction
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
const EdgeID via_edge,
const ConnectedRoad &candidate) const;
const TurnCandidate &candidate) const;
// Helper Function that decides between NoTurn or NewName
TurnInstruction
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const;
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const TurnCandidate &candidate) const;
// Basic Turn Handling
// Dead end.
std::vector<ConnectedRoad> handleOneWayTurn(std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleOneWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
// Mode Changes, new names...
std::vector<ConnectedRoad> handleTwoWayTurn(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleTwoWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
// Forks, T intersections and similar
std::vector<ConnectedRoad> handleThreeWayTurn(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleThreeWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
// Handling of turns larger then degree three
std::vector<ConnectedRoad> handleComplexTurn(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
// Normal Intersection. Can still contain forks...
std::vector<TurnCandidate> handleFourWayTurn(const NodeID from,
const EdgeID via_edge,
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
std::vector<ConnectedRoad> handleMotorwayJunction(
const EdgeID via_edge, std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleMotorwayJunction(
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleFromMotorway(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleFromMotorway(
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleMotorwayRamp(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> handleMotorwayRamp(
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
// Utility function, setting basic turn types. Prepares for normal turn handling.
std::vector<ConnectedRoad> setTurnTypes(const NodeID from,
std::vector<TurnCandidate> setTurnTypes(const NodeID from,
const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
std::vector<TurnCandidate> turn_candidates) 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
void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
void assignFork(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
void assignFork(const EdgeID via_edge,
ConnectedRoad &left,
ConnectedRoad &center,
ConnectedRoad &right) const;
TurnCandidate &left,
TurnCandidate &center,
TurnCandidate &right) const;
void
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) 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;
//Type specific fallbacks
std::vector<TurnCandidate>
fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) const;
}; // class TurnAnalysis
@@ -42,16 +42,8 @@ enum TurnType // at the moment we can support 32 turn types, without increasing
NewName, // no turn, but name changes
Continue, // remain on a street
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
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
EndOfRoad, // T intersection
EnterRoundabout, // Entering a small Roundabout
-48
View File
@@ -1,48 +0,0 @@
#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
+2 -3
View File
@@ -19,8 +19,6 @@ namespace osrm
namespace extractor
{
class ProfileProperties;
/**
* Parses the relations that represents turn restrictions.
*
@@ -42,10 +40,11 @@ class ProfileProperties;
class RestrictionParser
{
public:
RestrictionParser(lua_State *lua_state, const ProfileProperties& properties);
RestrictionParser(lua_State *lua_state);
boost::optional<InputRestrictionContainer> TryParse(const osmium::Relation &relation) const;
private:
void ReadUseRestrictionsSetting(lua_State *lua_state);
void ReadRestrictionExceptions(lua_State *lua_state);
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
+3 -15
View File
@@ -1,11 +1,6 @@
#ifndef 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 <memory>
#include <mutex>
@@ -28,25 +23,18 @@ namespace extractor
class ScriptingEnvironment
{
public:
struct Context
{
ProfileProperties properties;
SourceContainer sources;
util::LuaState state;
};
explicit ScriptingEnvironment(const std::string &file_name);
ScriptingEnvironment(const ScriptingEnvironment &) = delete;
ScriptingEnvironment &operator=(const ScriptingEnvironment &) = delete;
Context &GetContex();
lua_State *GetLuaState();
private:
void InitContext(Context &context);
void InitLuaState(lua_State *lua_state);
std::mutex init_mutex;
std::string file_name;
tbb::enumerable_thread_specific<std::unique_ptr<Context>> script_contexts;
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
};
}
}
+23
View File
@@ -0,0 +1,23 @@
#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
-38
View File
@@ -1,38 +0,0 @@
/*
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 GeometriesT = engine::api::RouteParameters::GeometriesType;
using OverviewT = engine::api::RouteParameters::OverviewType;
using UturnsT = bool;
using UturnsT = std::vector<boost::optional<bool>>;
RouteParametersGrammar() : BaseParametersGrammar(root_rule, parameters)
{
@@ -72,9 +72,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar
overview_rule = qi::lit("overview=simplified")[set_simplified_type] |
qi::lit("overview=full")[set_full_type] |
qi::lit("overview=false")[set_false_type];
uturns_rule = qi::lit("uturns=default") | (qi::lit("uturns=") >> qi::bool_)[set_uturns];
uturns_rule = qi::lit("uturns=") >> -qi::bool_ % ";";
route_rule = steps_rule[set_steps] | alternatives_rule[set_alternatives] | geometries_rule |
overview_rule | uturns_rule;
overview_rule | uturns_rule[set_uturns];
root_rule =
query_rule >> -qi::lit(".json") >> -(qi::lit("?") >> (route_rule | base_rule) % '&');
-3
View File
@@ -52,9 +52,6 @@ class Server
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
util::SimpleLogger().Write() << "Listening on: " << acceptor.local_endpoint();
acceptor.async_accept(
new_connection->socket(),
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
-1
View File
@@ -41,7 +41,6 @@ struct SharedDataLayout
DATASOURCE_NAME_DATA,
DATASOURCE_NAME_OFFSETS,
DATASOURCE_NAME_LENGTHS,
PROPERTIES,
NUM_BLOCKS
};
+4 -4
View File
@@ -1,24 +1,24 @@
#ifndef STORAGE_HPP
#define STORAGE_HPP
#include "storage/storage_config.hpp"
#include <boost/filesystem/path.hpp>
#include <unordered_map>
#include <string>
namespace osrm
{
namespace storage
{
using DataPaths = std::unordered_map<std::string, boost::filesystem::path>;
class Storage
{
public:
Storage(StorageConfig config);
Storage(const DataPaths &data_paths);
int Run();
private:
StorageConfig config;
DataPaths paths;
};
}
}
-32
View File
@@ -1,32 +0,0 @@
#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
+5 -25
View File
@@ -3,34 +3,20 @@
#include "util/coordinate.hpp"
#include <boost/math/constants/constants.hpp>
#include <utility>
namespace osrm
{
namespace util
{
namespace coordinate_calculation
{
const constexpr long double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
const constexpr long double RAD = 0.017453292519943295769236907684886;
// 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)
const constexpr long double EARTH_RADIUS = 6372797.560856;
// radius used by WGS84
const constexpr double EARTH_RADIUS_WGS84 = 6378137.0;
namespace detail
namespace coordinate_calculation
{
// 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
// Does not return meters!
@@ -64,6 +50,9 @@ double perpendicularDistanceFromProjectedCoordinate(
Coordinate &nearest_location,
double &ratio);
double degToRad(const double degree);
double radToDeg(const double radian);
double bearing(const Coordinate first_coordinate, const Coordinate second_coordinate);
// Get angle of line segment (A,C)->(C,B)
@@ -75,17 +64,8 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
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);
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 coordinate_calculation
} // ns util
+2 -11
View File
@@ -18,19 +18,10 @@ namespace osrm
namespace util
{
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;
};
template <typename T> void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; }
// Check if the lua function <name> is defined
inline bool luaFunctionExists(lua_State *lua_state, const char *name)
inline bool lua_function_exists(lua_State *lua_state, const char *name)
{
luabind::object globals_table = luabind::globals(lua_state);
luabind::object lua_function = globals_table[name];
-31
View File
@@ -1,31 +0,0 @@
#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
+251
View File
@@ -0,0 +1,251 @@
#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
+87
View File
@@ -0,0 +1,87 @@
#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
-48
View File
@@ -1,48 +0,0 @@
#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
+3 -4
View File
@@ -91,10 +91,9 @@ surface_speeds = {
}
-- these need to be global because they are accesed externaly
properties.traffic_signal_penalty = 2
properties.use_turn_restrictions = false
properties.u_turn_penalty = 20
properties.allow_u_turn_at_via = true
traffic_signal_penalty = 2
use_turn_restrictions = false
u_turn_penalty = 20
local obey_oneway = true
local ignore_areas = true
+9 -9
View File
@@ -128,20 +128,20 @@ maxspeed_table = {
["uk:motorway"] = (70*1609)/1000
}
-- set profile properties
properties.u_turn_penalty = 20
properties.traffic_signal_penalty = 2
properties.use_turn_restrictions = true
-- these need to be global because they are accesed externaly
u_turn_penalty = 20
traffic_signal_penalty = 2
use_turn_restrictions = true
local side_road_speed_multiplier = 0.8
side_road_speed_multiplier = 0.8
local turn_penalty = 10
local turn_penalty = 10
-- Note: this biases right-side driving. Should be
-- inverted for left-driving countries.
local turn_bias = 1.2
local turn_bias = 1.2
local obey_oneway = true
local ignore_areas = true
local obey_oneway = true
local ignore_areas = true
local abs = math.abs
local min = math.min
+3 -5
View File
@@ -64,11 +64,9 @@ leisure_speeds = {
["track"] = walking_speed
}
properties.traffic_signal_penalty = 2
properties.u_turn_penalty = 2
properties.use_turn_restrictions = false
properties.allow_u_turn_at_via = true
traffic_signal_penalty = 2
u_turn_penalty = 2
use_turn_restrictions = false
local fallback_names = true
function get_exceptions(vector)
+4 -4
View File
@@ -32,15 +32,15 @@ end
function segment_function (source, target, distance, weight)
local sourceData = sources:interpolate(raster_source, source.lon, source.lat)
local targetData = sources:interpolate(raster_source, target.lon, target.lat)
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
local slope = math.abs(sourceData.datum - targetData.datum) / distance
io.write(" slope: " .. slope .. "\n")
io.write(" was speed: " .. weight.speed .. "\n")
print (" slope: " .. slope)
print (" was speed: " .. weight.speed)
weight.speed = weight.speed * (1 - (slope * 5))
io.write(" new speed: " .. weight.speed .. "\n")
print (" new speed: " .. weight.speed)
end
end
+4 -4
View File
@@ -32,15 +32,15 @@ end
function segment_function (source, target, distance, weight)
local sourceData = sources:query(raster_source, source.lon, source.lat)
local targetData = sources:query(raster_source, target.lon, target.lat)
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
local slope = math.abs(sourceData.datum - targetData.datum) / distance
io.write(" slope: " .. slope .. "\n")
io.write(" was speed: " .. weight.speed .. "\n")
print (" slope: " .. slope)
print (" was speed: " .. weight.speed)
weight.speed = weight.speed * (1 - (slope * 5))
io.write(" new speed: " .. weight.speed .. "\n")
print (" new speed: " .. weight.speed)
end
end
+7 -4
View File
@@ -16,10 +16,13 @@ speed_profile = {
-- these settings are read directly by osrm
properties.allow_u_turn_at_via = false
properties.use_turn_restrictions = true
properties.traffic_signal_penalty = 7 -- seconds
properties.u_turn_penalty = 20
take_minimum_of_speeds = true
obey_oneway = true
obey_barriers = true
use_turn_restrictions = true
ignore_areas = true -- future feature
traffic_signal_penalty = 7 -- seconds
u_turn_penalty = 20
function limit_speed(speed, limits)
-- don't use ipairs(), since it stops at the first nil value
+21 -28
View File
@@ -173,10 +173,6 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
std::unordered_map<std::pair<OSMNodeID, OSMNodeID>, std::pair<unsigned, uint8_t>>
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)
{
uint8_t file_id = 1;
@@ -268,7 +264,7 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
// 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
// vector tiles later on.
m_geometry_datasource.resize(m_geometry_list.size(), 0);
std::vector<uint8_t> m_geometry_datasource(m_geometry_list.size(), 0);
// Now, we iterate over all the segments stored in the StaticRTree, updating
// the packed geometry weights in the `.geometries` file (note: we do not
@@ -406,36 +402,33 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
number_of_compressed_geometries *
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])),
number_of_datasource_entries * sizeof(uint8_t));
}
}
{
std::ofstream datasource_stream(datasource_names_filename, std::ios::binary);
if (!datasource_stream)
{
throw util::exception("Failed to open " + datasource_names_filename +
" for writing");
}
datasource_stream << "lua profile" << std::endl;
for (auto const &name : segment_speed_filenames)
{
datasource_stream << name << std::endl;
std::ofstream datasource_stream(datasource_names_filename, std::ios::binary);
if (!datasource_stream)
{
throw util::exception("Failed to open " + datasource_names_filename +
" for writing");
}
datasource_stream << "lua profile" << std::endl;
for (auto const &name : segment_speed_filenames)
{
datasource_stream << name << std::endl;
}
}
}
+5 -11
View File
@@ -40,11 +40,11 @@ const constexpr char *modifier_names[] = {"uturn",
// translations of TurnTypes. Not all types are exposed to the outside world.
// invalid types should never be returned as part of the API
const constexpr char *turn_type_names[] = {
"invalid", "no turn", "invalid", "new name", "continue", "turn",
"turn", "turn", "turn", "turn", "merge", "ramp",
"ramp", "ramp", "ramp", "ramp", "fork", "end of road",
"roundabout", "invalid", "roundabout", "invalid", "traffic circle", "invalid",
"traffic circle", "invalid", "invalid", "restriction", "notification"};
"invalid", "no turn", "invalid", "new name", "continue", "turn",
"merge", "ramp", "fork", "end of road", "roundabout", "invalid",
"roundabout", "invalid", "traffic circle", "invalid", "traffic circle", "invalid",
"invalid", "restriction", "notification"};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
// Check whether to include a modifier in the result of the API
@@ -149,12 +149,6 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
if (maneuver.exit != 0)
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;
}
+8 -10
View File
@@ -27,30 +27,28 @@ struct CoordinatePairCalculator
CoordinatePairCalculator(const util::Coordinate coordinate_a,
const util::Coordinate coordinate_b)
{
using namespace util::coordinate_calculation;
// initialize distance calculator with two fixed coordinates a, b
first_lon = static_cast<double>(toFloating(coordinate_a.lon)) * DEGREE_TO_RAD;
first_lat = static_cast<double>(toFloating(coordinate_a.lat)) * DEGREE_TO_RAD;
second_lon = static_cast<double>(toFloating(coordinate_b.lon)) * DEGREE_TO_RAD;
second_lat = static_cast<double>(toFloating(coordinate_b.lat)) * DEGREE_TO_RAD;
first_lon = static_cast<double>(toFloating(coordinate_a.lon)) * util::RAD;
first_lat = static_cast<double>(toFloating(coordinate_a.lat)) * util::RAD;
second_lon = static_cast<double>(toFloating(coordinate_b.lon)) * util::RAD;
second_lat = static_cast<double>(toFloating(coordinate_b.lat)) * util::RAD;
}
int operator()(const util::Coordinate other) const
{
using namespace util::coordinate_calculation;
// set third coordinate c
const float float_lon1 = static_cast<double>(toFloating(other.lon)) * DEGREE_TO_RAD;
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * DEGREE_TO_RAD;
const float float_lon1 = static_cast<double>(toFloating(other.lon)) * util::RAD;
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * util::RAD;
// compute distance (a,c)
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 dist1 = std::hypot(x_value_1, y_value_1) * EARTH_RADIUS;
const float dist1 = std::hypot(x_value_1, y_value_1) * util::EARTH_RADIUS;
// compute distance (b,c)
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 dist2 = std::hypot(x_value_2, y_value_2) * EARTH_RADIUS;
const float dist2 = std::hypot(x_value_2, y_value_2) * util::EARTH_RADIUS;
// return the minimum
return static_cast<int>(std::min(dist1, dist2));
+3 -5
View File
@@ -18,6 +18,7 @@
#include "storage/shared_barriers.hpp"
#include "util/make_unique.hpp"
#include "util/routed_options.hpp"
#include "util/simple_logger.hpp"
#include <boost/assert.hpp>
@@ -135,11 +136,8 @@ Engine::Engine(EngineConfig &config)
}
else
{
if (!config.storage_config.IsValid())
{
throw util::exception("Invalid file paths given!");
}
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.storage_config);
util::populate_base_path(config.server_paths);
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.server_paths);
}
// Register plugins
-27
View File
@@ -1,27 +0,0 @@
#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;
}
}
}
+13 -10
View File
@@ -3,7 +3,7 @@
#include "engine/guidance/leg_geometry.hpp"
#include "engine/douglas_peucker.hpp"
#include "util/viewport.hpp"
#include "util/tiles.hpp"
#include <vector>
#include <tuple>
@@ -23,22 +23,25 @@ namespace
unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometries)
{
util::Coordinate south_west{util::FixedLongitude{std::numeric_limits<int>::max()}, util::FixedLatitude{std::numeric_limits<int>::max()}};
util::Coordinate north_east{util::FixedLongitude{std::numeric_limits<int>::min()}, util::FixedLatitude{std::numeric_limits<int>::min()}};
util::FixedLongitude min_lon{std::numeric_limits<int>::max()};
util::FixedLongitude max_lon{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 coord : leg_geometry.locations)
{
south_west.lon = std::min(south_west.lon, coord.lon);
south_west.lat = std::min(south_west.lat, coord.lat);
north_east.lon = std::max(north_east.lon, coord.lon);
north_east.lat = std::max(north_east.lat, coord.lat);
min_lon = std::min(min_lon, coord.lon);
max_lon = std::max(max_lon, coord.lon);
min_lat = std::min(min_lat, coord.lat);
max_lat = std::max(max_lat, coord.lat);
}
}
return util::viewport::getFittedZoom(south_west, north_east);
return util::tiles::getBBMaxZoomTile(toFloating(min_lon), toFloating(min_lat),
toFloating(max_lon), toFloating(max_lat))
.z;
}
std::vector<util::Coordinate> simplifyGeometry(const std::vector<LegGeometry> &leg_geometries,
@@ -67,7 +70,7 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
{
if (use_simplification)
{
const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries));
const auto zoom_level = calculateOverviewZoomLevel(leg_geometries);
return simplifyGeometry(leg_geometries, zoom_level);
}
BOOST_ASSERT(!use_simplification);
+4 -46
View File
@@ -12,49 +12,15 @@ namespace guidance
{
namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
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 std::size_t segment_index)
const std::size_t segment_index,
const unsigned exit)
{
auto turn_index = leg_geometry.BackIndex(segment_index);
BOOST_ASSERT(turn_index > 0);
BOOST_ASSERT(turn_index + 1 < leg_geometry.locations.size());
BOOST_ASSERT(turn_index < leg_geometry.locations.size());
// TODO chose a bigger look-a-head to smooth complex geometry
const auto pre_turn_coordinate = leg_geometry.locations[turn_index - 1];
@@ -66,15 +32,7 @@ StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instr
const double post_turn_bearing =
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
return StepManeuver{
std::move(turn_coordinate),
pre_turn_bearing,
post_turn_bearing,
std::move(instruction),
WaypointType::None,
INVALID_EXIT_NR,
{} // no intermediate intersections
};
return StepManeuver{turn_coordinate, pre_turn_bearing, post_turn_bearing, instruction, waypoint_type, exit};
}
} // ns detail
} // ns engine
+141 -244
View File
@@ -4,11 +4,8 @@
#include "engine/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <iostream>
#include <cstddef>
#include <utility>
#include <vector>
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
using TurnType = osrm::extractor::guidance::TurnType;
@@ -23,296 +20,196 @@ namespace guidance
namespace detail
{
bool canMergeTrivially(const RouteStep &destination, const RouteStep &source)
bool canMergeTrivially(const PathData &destination, const PathData &source)
{
return destination.maneuver.exit == 0 && destination.name_id == source.name_id &&
isSilent(source.maneuver.instruction);
return destination.exit == 0 && destination.name_id == source.name_id &&
destination.travel_mode == source.travel_mode && isSilent(source.turn_instruction);
}
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
PathData forwardInto(PathData destination, const PathData &source)
{
// Merge a turn into a silent turn
// Overwrites turn instruction and increases exit NR
destination.duration += source.duration;
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);
destination.duration_until_turn += source.duration_until_turn;
destination.exit = source.exit;
return destination;
}
void fixFinalRoundabout(std::vector<RouteStep> &steps)
PathData accumulateInto(PathData destination, const PathData &source)
{
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
--propagation_index)
{
auto &propagation_step = steps[propagation_index];
if (entersRoundabout(propagation_step.maneuver.instruction))
{
propagation_step.maneuver.exit = 0;
propagation_step.geometry_end = steps.back().geometry_begin;
break;
}
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
}
}
// Merge a turn into a silent turn
// Overwrites turn instruction and increases exit NR
BOOST_ASSERT(canMergeTrivially(destination, source));
destination.duration_until_turn += source.duration_until_turn;
destination.exit = source.exit + 1;
return destination;
}
bool setUpRoundabout(RouteStep &step)
PathData mergeInto(PathData destination, const PathData &source)
{
// basic entry into a roundabout
// 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)
if (source.turn_instruction == TurnInstruction::NO_TURN())
{
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;
BOOST_ASSERT(canMergeTrivially(destination, source));
return detail::forwardInto(destination, source);
}
if (leavesRoundabout(instruction))
if (source.turn_instruction.type == TurnType::Suppressed)
{
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;
return detail::forwardInto(destination, source);
}
else
if (source.turn_instruction.type == TurnType::StayOnRoundabout)
{
return true;
return detail::forwardInto(destination, source);
}
if (entersRoundabout(source.turn_instruction))
{
return detail::forwardInto(destination, source);
}
return destination;
}
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)
void print(const std::vector<std::vector<PathData>> &leg_data)
{
std::cout << "Path\n";
int segment = 0;
for (const auto &step : steps)
int legnr = 0;
for (const auto &leg : leg_data)
{
const auto type = static_cast<int>(step.maneuver.instruction.type);
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
std::cout << "\tLeg: " << ++legnr << "\n";
int segment = 0;
for (const auto &data : leg)
{
const auto type = static_cast<int>(data.turn_instruction.type);
const auto modifier = static_cast<int>(data.turn_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;
std::cout << "\t\t[" << ++segment << "]: " << type << " " << modifier
<< " exit: " << data.exit << "\n";
}
}
std::cout << 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)
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
{
// 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;
if (leg_data.empty())
return leg_data;
#define OSRM_POST_PROCESSING_PRINT_DEBUG 0
#if OSRM_POST_PROCESSING_PRINT_DEBUG
#define PRINT_DEBUG 0
unsigned carry_exit = 0;
#if PRINT_DEBUG
std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
std::cout << "Input\n";
print(steps);
print(leg_data);
#endif
// Count Street Exits forward
bool on_roundabout = false;
// 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)
for (auto &path_data : leg_data)
{
into.maneuver.intersections.push_back(
{last_step.duration, last_step.distance, intersection.maneuver.location});
if (not path_data.empty())
path_data[0].exit = carry_exit;
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))
for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
{
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)
if (entersRoundabout(path_data[data_index].turn_instruction))
{
// in case the we are not on a roundabout, the very first instruction
// after the depart will be transformed into a roundabout and become
// the first valid instruction
last_valid_instruction = 1;
path_data[data_index].exit += 1;
on_roundabout = true;
}
detail::closeOffRoundabout(on_roundabout, steps, step_index);
on_roundabout = false;
}
else if (instruction.type == TurnType::Suppressed)
{
// count intersections. We cannot use exit, since intersections can follow directly
// after a roundabout
steps[last_valid_instruction] = addIntersection(
std::move(steps[last_valid_instruction]), steps[step_index - 1], step);
step.maneuver.instruction = TurnInstruction::NO_TURN();
}
else if (!isSilent(instruction))
{
// Remember the last non silent instruction
last_valid_instruction = step_index;
if (isSilent(path_data[data_index].turn_instruction) &&
path_data[data_index].turn_instruction != TurnInstruction::NO_TURN())
{
path_data[data_index].exit += 1;
}
if (leavesRoundabout(path_data[data_index].turn_instruction))
{
if (!on_roundabout)
{
BOOST_ASSERT(leg_data[0][0].turn_instruction.type ==
TurnInstruction::NO_TURN());
if (path_data[data_index].turn_instruction.type == TurnType::ExitRoundabout)
leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
if (path_data[data_index].turn_instruction.type == TurnType::ExitRotary)
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;
}
}
// 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
#if PRINT_DEBUG
std::cout << "Merged\n";
print(steps);
print(leg_data);
#endif
return steps;
}
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)
on_roundabout = false;
// Move Roundabout exit numbers to front
for (auto rev_itr = leg_data.rbegin(); rev_itr != leg_data.rend(); ++rev_itr)
{
leg_geometry.segment_distances.push_back(step.distance);
// the leg geometry does not follow the begin/end-convetion. So we have to subtract one
// to get the back-index.
leg_geometry.segment_offsets.push_back(step.geometry_end - 1);
auto &path_data = *rev_itr;
for (std::size_t data_index = path_data.size(); data_index > 1; --data_index)
{
if (entersRoundabout(path_data[data_index - 1].turn_instruction))
{
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;
}
}
//remove the data fromt the reached-target step again
leg_geometry.segment_offsets.pop_back();
leg_geometry.segment_distances.pop_back();
#if PRINT_DEBUG
std::cout << "Move To Front\n";
print(leg_data);
#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_geometry;
return leg_data;
}
} // namespace guidance
+5 -45
View File
@@ -1,60 +1,20 @@
#include "engine/hint.hpp"
#include "engine/base64.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/object_encoder.hpp"
#include <boost/assert.hpp>
#include <iterator>
#include <algorithm>
#include <ostream>
#include <tuple>
namespace osrm
{
namespace engine
{
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;
}
std::string Hint::ToBase64() const { return encodeBase64(*this); }
Hint Hint::FromBase64(const std::string &base64Hint)
{
BOOST_ASSERT_MSG(base64Hint.size() == ENCODED_HINT_SIZE, "Hint has invalid size");
// We need mutability but don't want to change the API
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);
auto decoded = decodeBase64<Hint>(base64Hint);
return decoded;
}
}
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
+1
View File
@@ -4,6 +4,7 @@
#include "engine/map_matching/bayes_classifier.hpp"
#include "engine/api/match_parameters.hpp"
#include "engine/api/match_api.hpp"
#include "engine/object_encoder.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/integer_range.hpp"
#include "util/json_logger.hpp"
+1
View File
@@ -2,6 +2,7 @@
#include "engine/api/table_parameters.hpp"
#include "engine/api/table_api.hpp"
#include "engine/object_encoder.hpp"
#include "engine/routing_algorithms/many_to_many.hpp"
#include "engine/search_engine_data.hpp"
#include "util/string_util.hpp"
+187 -209
View File
@@ -1,13 +1,6 @@
#include "engine/plugins/plugin_base.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/pbf_writer.hpp>
@@ -24,30 +17,89 @@ namespace engine
{
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;
// Simple container class for WSG84 coordinates
template <typename T> struct Point final
{
Point(T _x, T _y) : x(_x), y(_y) {}
const T x;
const T y;
};
// from mapnik/well_known_srs.hpp
const constexpr double EARTH_RADIUS = 6378137.0;
const constexpr double EARTH_DIAMETER = EARTH_RADIUS * 2.0;
const constexpr double EARTH_CIRCUMFERENCE = EARTH_DIAMETER * M_PI;
const constexpr double MAXEXTENT = EARTH_CIRCUMFERENCE / 2.0;
const constexpr double M_PI_by2 = M_PI / 2.0;
const constexpr double D2R = M_PI / 180.0;
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
namespace pbf
namespace detail_pbf
{
inline unsigned encode_length(const unsigned len) { return (len << 3u) | 2u; }
}
struct BBox final
// Converts a regular WSG84 lon/lat pair into
// a mercator coordinate
inline void lonlat2merc(double &x, double &y)
{
BBox(const double _minx, const double _miny, const double _maxx, const double _maxy)
if (x > 180)
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)
{
}
@@ -61,6 +113,15 @@ struct BBox final
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)
struct point_type_i final
{
@@ -70,23 +131,15 @@ struct point_type_i final
const std::int64_t y;
};
using FixedLine = std::vector<detail::Point<std::int32_t>>;
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));
using line_type = std::vector<point_type_i>;
using line_typed = std::vector<point_type_d>;
// from mapnik-vector-tile
// Encodes a linestring using protobuf zigzag encoding
inline bool encodeLinestring(const FixedLine &line,
protozero::packed_field_uint32 &geometry,
std::int32_t &start_x,
std::int32_t &start_y)
inline bool encode_linestring(line_type line,
protozero::packed_field_uint32 &geometry,
std::int32_t &start_x,
std::int32_t &start_y)
{
const std::size_t line_size = line.size();
if (line_size < 2)
@@ -102,7 +155,7 @@ inline bool encodeLinestring(const FixedLine &line,
geometry.add_element(protozero::encode_zigzag32(pt->y - start_y));
start_x = pt->x;
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)
{
const std::int32_t dx = pt->x - start_x;
@@ -115,65 +168,15 @@ inline bool encodeLinestring(const FixedLine &line,
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 &parameters, 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;
// Convert the z,x,y mercator tile coordinates into WSG84 lon/lat values
mercator::xyzToWSG84(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon,
max_lat);
xyz2wsg84(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 northeast{util::FloatLongitude(max_lon), util::FloatLatitude(max_lat)};
@@ -182,70 +185,13 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// This hits the OSRM StaticRTree
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
// Convert tile coordinates into mercator coordinates
mercator::xyzToMercator(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon,
max_lat);
const detail::BBox tile_bbox{min_lon, min_lat, max_lon, max_lat};
xyz2mercator(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon, max_lat);
const 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
// the extra scoping below.
@@ -317,11 +263,38 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
max_datasource_id = std::max(max_datasource_id, forward_datasource);
max_datasource_id = std::max(max_datasource_id, reverse_datasource);
const auto encode_tile_line = [&layer_writer, &edge, &id, &max_datasource_id](
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)
// 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;
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
// is_small
// boolean. We onl serve up speeds from 0-139, so all we do is save the
@@ -343,39 +316,17 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
field.add_element(0); // "speed" tag key offset
field.add_element(
std::min(speed_kmh, 127u)); // save the speed value, capped at 127
field.add_element(1); // "is_small" tag key offset
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 + datasource); // datasource value offset
field.add_element(3); // "duration" tag key offset
field.add_element(130 + max_datasource_id + 1 +
duration); // duration value offset
field.add_element(2); // "datasource" tag key offset
field.add_element(130 + forward_datasource); // datasource value offset
}
{
// Encode the geometry for the feature
protozero::packed_field_uint32 geometry(feature_writer, 4);
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);
encode_linestring(tile_line, geometry, start_x, start_y);
}
}
@@ -386,15 +337,48 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
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 / reverse_weight * 10 * 3.6));
line_typed geo_line;
geo_line.emplace_back(static_cast<double>(util::toFloating(b.lon)),
static_cast<double>(util::toFloating(b.lat)));
geo_line.emplace_back(static_cast<double>(util::toFloating(a.lon)),
static_cast<double>(util::toFloating(a.lat)));
auto tile_line = coordinatesToTileLine(b, a, tile_bbox);
if (!tile_line.empty())
const auto speed =
static_cast<const std::uint32_t>(round(length / reverse_weight * 10 * 3.6));
line_type tile_line;
for (auto const &pt : geo_line)
{
encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight],
reverse_datasource, start_x, start_y);
double px_merc = pt.x;
double py_merc = pt.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);
}
}
}
@@ -406,17 +390,18 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
layer_writer.add_string(3, "speed");
layer_writer.add_string(3, "is_small");
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
// 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)
for (std::size_t i = 0; i < 128; i++)
{
// Writing field type 4 == variant type
protozero::pbf_writer values_writer(layer_writer, 4);
// Attribute value 5 == uin64 type
values_writer.add_uint64(5, i);
{
// Writing field type 4 == variant type
protozero::pbf_writer values_writer(layer_writer, 4);
// Attribute value 5 == uin64 type
values_writer.add_uint64(5, i);
}
}
{
protozero::pbf_writer values_writer(layer_writer, 4);
@@ -430,19 +415,12 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
}
for (std::size_t i = 0; i <= max_datasource_id; i++)
{
// Writing field type 4 == variant type
protozero::pbf_writer values_writer(layer_writer, 4);
// Attribute value 1 == string type
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.);
{
// Writing field type 4 == variant type
protozero::pbf_writer values_writer(layer_writer, 4);
// Attribute value 1 == string type
values_writer.add_string(1, facade.GetDatasourceName(i));
}
}
}
+13 -1
View File
@@ -135,7 +135,19 @@ InternalRouteResult TripPlugin::ComputeRoute(const std::vector<PhantomNode> &sna
}
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size());
shortest_path(min_route.segment_end_coordinates, parameters.uturns, min_route);
std::vector<boost::optional<bool>> uturns;
if (parameters.uturns.size() > 0)
{
uturns.resize(trip.size() + 1);
std::transform(trip.begin(), trip.end(), uturns.begin(), [&parameters](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");
return min_route;
+1
View File
@@ -1,6 +1,7 @@
#include "engine/plugins/viaroute.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/api/route_api.hpp"
#include "engine/object_encoder.hpp"
#include "engine/status.hpp"
#include "util/for_each_pair.hpp"
+33 -37
View File
@@ -12,7 +12,6 @@
#include "extractor/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <algorithm>
#include <cmath>
@@ -35,13 +34,12 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table)
SpeedProfileProperties speed_profile)
: m_max_edge_id(0), m_node_info_list(node_info_list),
m_node_based_graph(std::move(node_based_graph)),
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
profile_properties(std::move(profile_properties)), name_table(name_table)
speed_profile(std::move(speed_profile))
{
}
@@ -125,9 +123,10 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
// traverse arrays from start and end respectively
for (const auto i : util::irange(0UL, geometry_size))
{
BOOST_ASSERT(current_edge_source_coordinate_id ==
m_compressed_edge_container.GetBucketReference(
edge_id_2)[geometry_size - 1 - i].node_id);
BOOST_ASSERT(
current_edge_source_coordinate_id ==
m_compressed_edge_container.GetBucketReference(edge_id_2)[geometry_size - 1 - 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);
@@ -208,7 +207,7 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
// oneway streets always require this self-loop. Other streets only if a u-turn plus
// traversal
// of the street takes longer than the loop
m_edge_based_node_weights.push_back(edge_data.distance + profile_properties.u_turn_penalty);
m_edge_based_node_weights.push_back(edge_data.distance + speed_profile.u_turn_penalty);
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
edge_data.edge_id = numbered_edges_count;
@@ -277,9 +276,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
{
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 original_edges_counter = 0;
restricted_turns_counter = 0;
@@ -296,10 +292,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
edge_penalty_file.open(edge_fixed_penalties_filename.c_str(), std::ios::binary);
}
// Writes a dummy value at the front that is updated later with the total length
const unsigned length_prefix_empty_space{0};
edge_data_file.write(reinterpret_cast<const char *>(&length_prefix_empty_space),
sizeof(length_prefix_empty_space));
// writes a dummy value that is updated later
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
std::vector<OriginalEdgeData> original_edge_data_vector;
original_edge_data_vector.reserve(1024 * 1024);
@@ -308,8 +302,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// Three nested loop look super-linear, but we are dealing with a (kind of)
// linear number of turns only.
util::Percent progress(m_node_based_graph->GetNumberOfNodes());
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
m_barrier_nodes, m_compressed_edge_container, name_table);
guidance::TurnAnalysis turn_analysis( *m_node_based_graph, m_node_info_list,
*m_restriction_map, m_barrier_nodes, m_compressed_edge_container );
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
// progress.printStatus(node_u);
@@ -321,12 +315,15 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
}
++node_based_edge_counter;
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);
auto turn_candidates = turn_analysis.getTurns(node_u, edge_from_u);
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
for (const auto turn : possible_turns)
for (const auto turn : turn_candidates)
{
if (!turn.valid)
continue;
const double turn_angle = turn.angle;
// only add an edge if turn is not prohibited
@@ -341,15 +338,15 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
unsigned distance = edge_data1.distance;
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
{
distance += profile_properties.traffic_signal_penalty;
distance += speed_profile.traffic_signal_penalty;
}
const int turn_penalty = use_turn_function ? GetTurnPenalty(turn_angle, lua_state) : 0;
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
const auto turn_instruction = turn.instruction;
if (guidance::isUturn(turn_instruction))
{
distance += profile_properties.u_turn_penalty;
distance += speed_profile.u_turn_penalty;
}
distance += turn_penalty;
@@ -425,13 +422,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
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);
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));
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
util::SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
<< " edge based nodes";
@@ -449,16 +441,20 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
{
BOOST_ASSERT(lua_state != nullptr);
try
if (speed_profile.has_turn_penalty_function)
{
// call lua profile to compute turn penalty
double penalty = luabind::call_function<double>(lua_state, "turn_function", 180. - angle);
return boost::numeric_cast<int>(penalty);
}
catch (const luabind::error &er)
{
util::SimpleLogger().Write(logWARNING) << er.what();
try
{
// call lua profile to compute turn penalty
double penalty =
luabind::call_function<double>(lua_state, "turn_function", 180. - angle);
return static_cast<int>(penalty);
}
catch (const luabind::error &er)
{
util::SimpleLogger().Write(logWARNING) << er.what();
}
}
return 0;
}
+1 -3
View File
@@ -288,8 +288,6 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
const auto all_edges_list_end_ = all_edges_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_)
{
// skip all invalid edges
@@ -325,7 +323,7 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
edge_iterator->source_coordinate,
util::Coordinate(node_iterator->lon, node_iterator->lat));
if (has_segment_function)
if (util::lua_function_exists(segment_state, "segment_function"))
{
luabind::call_function<void>(
segment_state, "segment_function", boost::cref(edge_iterator->source_coordinate),
+66 -35
View File
@@ -15,7 +15,6 @@
#include "util/timing_util.hpp"
#include "util/lua_util.hpp"
#include "util/graph_loader.hpp"
#include "util/name_table.hpp"
#include "util/typedefs.hpp"
@@ -48,7 +47,6 @@
#include <unordered_map>
#include <vector>
#include <bitset>
#include <chrono>
namespace osrm
{
@@ -76,9 +74,6 @@ namespace extractor
*/
int Extractor::run()
{
// setup scripting environment
ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
try
{
util::LogPolicy::GetInstance().Unmute();
@@ -93,6 +88,9 @@ int Extractor::run()
util::SimpleLogger().Write() << "Profile: " << config.profile_path.filename().string();
util::SimpleLogger().Write() << "Threads: " << number_of_threads;
// setup scripting environment
ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
ExtractionContainers extraction_containers;
auto extractor_callbacks = util::make_unique<ExtractorCallbacks>(extraction_containers);
@@ -108,12 +106,15 @@ int Extractor::run()
util::SimpleLogger().Write() << "Parsing in progress..";
TIMER_START(parsing);
auto& main_context = scripting_environment.GetContex();
lua_State *segment_state = scripting_environment.GetLuaState();
// setup raster sources
if (util::luaFunctionExists(main_context.state, "source_function"))
if (util::lua_function_exists(segment_state, "source_function"))
{
luabind::call_function<void>(main_context.state, "source_function");
// bind a single instance of SourceContainer class to relevant lua state
SourceContainer sources;
luabind::globals(segment_state)["sources"] = sources;
luabind::call_function<void>(segment_state, "source_function");
}
std::string generator = header.get("generator");
@@ -140,7 +141,7 @@ int Extractor::run()
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
// setup restriction parser
const RestrictionParser restriction_parser(main_context.state, main_context.properties);
const RestrictionParser restriction_parser(scripting_environment.GetLuaState());
while (const osmium::memory::Buffer buffer = reader.read())
{
@@ -163,7 +164,7 @@ int Extractor::run()
{
ExtractionNode result_node;
ExtractionWay result_way;
auto& local_context = scripting_environment.GetContex();
lua_State *local_state = scripting_environment.GetLuaState();
for (auto x = range.begin(), end = range.end(); x != end; ++x)
{
@@ -175,7 +176,7 @@ int Extractor::run()
result_node.clear();
++number_of_nodes;
luabind::call_function<void>(
local_context.state, "node_function",
local_state, "node_function",
boost::cref(static_cast<const osmium::Node &>(*entity)),
boost::ref(result_node));
resulting_nodes.push_back(std::make_pair(x, result_node));
@@ -184,7 +185,7 @@ int Extractor::run()
result_way.clear();
++number_of_ways;
luabind::call_function<void>(
local_context.state, "way_function",
local_state, "way_function",
boost::cref(static_cast<const osmium::Way &>(*entity)),
boost::ref(result_way));
resulting_ways.push_back(std::make_pair(x, result_way));
@@ -236,29 +237,26 @@ int Extractor::run()
}
extraction_containers.PrepareData(config.output_file_name, config.restriction_file_name,
config.names_file_name, main_context.state);
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
config.names_file_name, segment_state);
TIMER_STOP(extracting);
util::SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting)
<< "s";
}
// we do this for scoping
// TODO move to own functions
catch (const std::exception &e)
{
util::SimpleLogger().Write(logWARNING) << e.what();
return 1;
}
try
{
// 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
// movement (e.g. turn from A->B, and B->A) becomes an edge
//
auto& main_context = scripting_environment.GetContex();
//
// // Create a new lua state
util::SimpleLogger().Write() << "Generating edge-expanded graph representation";
@@ -269,9 +267,7 @@ int Extractor::run()
std::vector<bool> node_is_startpoint;
std::vector<EdgeWeight> edge_based_node_weights;
std::vector<QueryNode> internal_to_external_node_map;
auto graph_size = BuildEdgeExpandedGraph(main_context.state,
main_context.properties,
internal_to_external_node_map,
auto graph_size = BuildEdgeExpandedGraph(internal_to_external_node_map,
edge_based_node_list, node_is_startpoint,
edge_based_node_weights, edge_based_edge_list);
@@ -317,15 +313,46 @@ int Extractor::run()
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)
{
boost::filesystem::ofstream out_stream(output_path);
if (!out_stream)
// open utility libraries string library;
luaL_openlibs(lua_state);
// 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()))
{
throw util::exception("Could not open " + output_path + " for writing.");
std::stringstream msg;
msg << lua_tostring(lua_state, -1) << " occurred in scripting block";
throw util::exception(msg.str());
}
out_stream.write(reinterpret_cast<const char*>(&properties), sizeof(properties));
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
{
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,
@@ -468,14 +495,18 @@ Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
\brief Building an edge-expanded graph from node-based input and turn restrictions
*/
std::pair<std::size_t, std::size_t>
Extractor::BuildEdgeExpandedGraph(lua_State* lua_state,
const ProfileProperties& profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
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> traffic_lights;
@@ -484,23 +515,23 @@ Extractor::BuildEdgeExpandedGraph(lua_State* lua_state,
LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map);
CompressedEdgeContainer compressed_edge_container;
GraphCompressor graph_compressor;
GraphCompressor graph_compressor(speed_profile);
graph_compressor.Compress(barrier_nodes, traffic_lights, *restriction_map, *node_based_graph,
compressed_edge_container);
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
util::NameTable name_table(config.names_file_name);
EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights,
std::const_pointer_cast<RestrictionMap const>(restriction_map),
internal_to_external_node_map, profile_properties, name_table);
internal_to_external_node_map, speed_profile);
edge_based_graph_factory.Run(config.edge_output_path, lua_state,
config.edge_segment_lookup_path, config.edge_penalty_path,
config.generate_edge_lookup);
lua_close(lua_state);
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
+5
View File
@@ -13,6 +13,11 @@ namespace osrm
namespace extractor
{
GraphCompressor::GraphCompressor(SpeedProfileProperties speed_profile)
: speed_profile(std::move(speed_profile))
{
}
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
RestrictionMap &restriction_map,
File diff suppressed because it is too large Load Diff
+23 -4
View File
@@ -1,5 +1,5 @@
#include "extractor/restriction_parser.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/external_memory_node.hpp"
#include "util/lua_util.hpp"
@@ -33,18 +33,37 @@ int luaErrorCallback(lua_State *lua_state)
}
}
RestrictionParser::RestrictionParser(lua_State *lua_state, const ProfileProperties &properties)
: use_turn_restrictions(properties.use_turn_restrictions)
RestrictionParser::RestrictionParser(lua_State *lua_state) : use_turn_restrictions(true)
{
ReadUseRestrictionsSetting(lua_state);
if (use_turn_restrictions)
{
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)
{
if (util::luaFunctionExists(lua_state, "get_exceptions"))
if (util::lua_function_exists(lua_state, "get_exceptions"))
{
luabind::set_pcall_callback(&luaErrorCallback);
// get list of turn restriction exceptions
+82 -93
View File
@@ -6,9 +6,7 @@
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/raster_source.hpp"
#include "extractor/profile_properties.hpp"
#include "util/lua_util.hpp"
#include "util/make_unique.hpp"
#include "util/exception.hpp"
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
@@ -58,126 +56,117 @@ ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) : file_
util::SimpleLogger().Write() << "Using script " << file_name;
}
void ScriptingEnvironment::InitContext(ScriptingEnvironment::Context &context)
void ScriptingEnvironment::InitLuaState(lua_State *lua_state)
{
typedef double (osmium::Location::*location_member_ptr_type)() const;
luabind::open(context.state);
luabind::open(lua_state);
// open utility libraries string library;
luaL_openlibs(context.state);
luaL_openlibs(lua_state);
util::luaAddScriptFolderToLoadPath(context.state, file_name.c_str());
util::luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
// Add our function to the state's global scope
luabind::module(context.state)
[luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration),
luabind::class_<TravelMode>("mode")
.enum_("enums")[luabind::value("inaccessible", TRAVEL_MODE_INACCESSIBLE),
luabind::value("driving", TRAVEL_MODE_DRIVING),
luabind::value("cycling", TRAVEL_MODE_CYCLING),
luabind::value("walking", TRAVEL_MODE_WALKING),
luabind::value("ferry", TRAVEL_MODE_FERRY),
luabind::value("train", TRAVEL_MODE_TRAIN),
luabind::value("pushing_bike", TRAVEL_MODE_PUSHING_BIKE),
luabind::value("movable_bridge", TRAVEL_MODE_MOVABLE_BRIDGE),
luabind::value("steps_up", TRAVEL_MODE_STEPS_UP),
luabind::value("steps_down", TRAVEL_MODE_STEPS_DOWN),
luabind::value("river_up", TRAVEL_MODE_RIVER_UP),
luabind::value("river_down", TRAVEL_MODE_RIVER_DOWN),
luabind::value("route", TRAVEL_MODE_ROUTE)],
luabind::class_<SourceContainer>("sources")
.def(luabind::constructor<>())
.def("load", &SourceContainer::loadRasterSource)
.def("query", &SourceContainer::getRasterDataFromSource)
.def("interpolate", &SourceContainer::getRasterInterpolateFromSource),
luabind::class_<const float>("constants")
.enum_("enums")[luabind::value("precision", COORDINATE_PRECISION)],
luabind::module(
lua_state)[luabind::def("print", util::LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration),
luabind::class_<TravelMode>("mode")
.enum_("enums")[luabind::value("inaccessible", TRAVEL_MODE_INACCESSIBLE),
luabind::value("driving", TRAVEL_MODE_DRIVING),
luabind::value("cycling", TRAVEL_MODE_CYCLING),
luabind::value("walking", TRAVEL_MODE_WALKING),
luabind::value("ferry", TRAVEL_MODE_FERRY),
luabind::value("train", TRAVEL_MODE_TRAIN),
luabind::value("pushing_bike", TRAVEL_MODE_PUSHING_BIKE),
luabind::value("movable_bridge", TRAVEL_MODE_MOVABLE_BRIDGE),
luabind::value("steps_up", TRAVEL_MODE_STEPS_UP),
luabind::value("steps_down", TRAVEL_MODE_STEPS_DOWN),
luabind::value("river_up", TRAVEL_MODE_RIVER_UP),
luabind::value("river_down", TRAVEL_MODE_RIVER_DOWN),
luabind::value("route", TRAVEL_MODE_ROUTE)],
luabind::class_<SourceContainer>("sources")
.def(luabind::constructor<>())
.def("load", &SourceContainer::loadRasterSource)
.def("query", &SourceContainer::getRasterDataFromSource)
.def("interpolate", &SourceContainer::getRasterInterpolateFromSource),
luabind::class_<const float>("constants")
.enum_("enums")[luabind::value("precision", COORDINATE_PRECISION)],
luabind::class_<ProfileProperties>("ProfileProperties")
.def(luabind::constructor<>())
.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_<std::vector<std::string>>("vector").def(
"Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back)),
luabind::class_<std::vector<std::string>>("vector")
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back)),
luabind::class_<osmium::Location>("Location")
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
luabind::class_<osmium::Location>("Location")
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
luabind::class_<osmium::Node>("Node")
// .def<node_member_ptr_type>("tags", &osmium::Node::tags)
.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_<osmium::Node>("Node")
// .def<node_member_ptr_type>("tags", &osmium::Node::tags)
.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_<ExtractionNode>("ResultNode")
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
.def_readwrite("barrier", &ExtractionNode::barrier),
luabind::class_<ExtractionNode>("ResultNode")
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
.def_readwrite("barrier", &ExtractionNode::barrier),
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::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()))
if (0 != luaL_dofile(lua_state, file_name.c_str()))
{
luabind::object error_msg(luabind::from_stack(context.state, -1));
luabind::object error_msg(luabind::from_stack(lua_state, -1));
std::ostringstream error_stream;
error_stream << error_msg;
throw util::exception("ERROR occurred in profile script:\n" + error_stream.str());
}
}
ScriptingEnvironment::Context &ScriptingEnvironment::GetContex()
lua_State *ScriptingEnvironment::GetLuaState()
{
std::lock_guard<std::mutex> lock(init_mutex);
bool initialized = false;
auto &ref = script_contexts.local(initialized);
if (!initialized)
{
ref = util::make_unique<Context>();
InitContext(*ref);
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
ref = state;
InitLuaState(ref.get());
}
luabind::set_pcall_callback(&luaErrorCallback);
return *ref;
return ref.get();
}
}
}
+3 -1
View File
@@ -25,7 +25,9 @@ std::string getWrongOptionHelp(const engine::api::RouteParameters &parameters)
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "bearings",
parameters.bearings, coord_size, help) ||
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)
{
+128 -69
View File
@@ -2,7 +2,6 @@
#include "util/range_table.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/query_node.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/static_graph.hpp"
@@ -73,12 +72,10 @@ void deleteRegion(const SharedDataType region)
}
}
Storage::Storage(StorageConfig config_) : config(std::move(config_)) {}
Storage::Storage(const DataPaths &paths_) : paths(paths_) {}
int Storage::Run()
{
BOOST_ASSERT_MSG(config.IsValid(), "Invalid storage config");
util::LogPolicy::GetInstance().Unmute();
SharedBarriers barrier;
@@ -102,6 +99,94 @@ int Storage::Run()
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 &timestamp_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
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
const storage::SharedDataType layout_region = [&]
@@ -124,19 +209,14 @@ int Storage::Run()
// Allocate a memory layout in shared memory, deallocate previous
auto *layout_memory = makeSharedMemory(layout_region, sizeof(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,
absolute_file_index_path.string().length() + 1);
file_index_path.length() + 1);
// collect number of elements to store in shared memory object
util::SimpleLogger().Write() << "load names from: " << config.names_data_path;
util::SimpleLogger().Write() << "load names from: " << names_data_path;
// number of entries in name index
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.");
}
boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
unsigned name_blocks = 0;
name_stream.read((char *)&name_blocks, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
@@ -150,11 +230,7 @@ int Storage::Run()
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
// Loading information for original edges
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.");
}
boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
unsigned number_of_original_edges = 0;
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
@@ -168,11 +244,7 @@ int Storage::Run()
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
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.");
}
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
util::FingerPrint fingerprint_loaded;
@@ -207,27 +279,39 @@ int Storage::Run()
number_of_graph_edges);
// load rsearch tree size
boost::filesystem::ifstream tree_node_file(config.ram_index_path, std::ios::binary);
boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
uint32_t tree_size = 0;
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
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
boost::filesystem::ifstream timestamp_stream(config.timestamp_path);
std::string m_timestamp;
getline(timestamp_stream, m_timestamp);
if (boost::filesystem::exists(timestamp_path))
{
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());
// load core marker size
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.");
}
boost::filesystem::ifstream core_marker_file(core_marker_path, std::ios::binary);
uint32_t number_of_core_markers = 0;
core_marker_file.read((char *)&number_of_core_markers, sizeof(uint32_t));
@@ -235,22 +319,14 @@ int Storage::Run()
number_of_core_markers);
// load coordinate size
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.");
}
boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
unsigned coordinate_list_size = 0;
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<util::Coordinate>(SharedDataLayout::COORDINATE_LIST,
coordinate_list_size);
// load geometries sizes
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.");
}
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(), std::ios::binary);
unsigned number_of_geometries_indices = 0;
unsigned number_of_compressed_geometries = 0;
@@ -265,12 +341,8 @@ int Storage::Run()
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
// exist.
boost::filesystem::ifstream geometry_datasource_input_stream(config.datasource_indexes_path,
std::ios::binary);
if (!geometry_datasource_input_stream)
{
throw util::exception("Could not open " + config.datasource_indexes_path.string() + " for reading.");
}
std::ifstream geometry_datasource_input_stream(datasource_indexes_path.c_str(),
std::ios::binary);
std::size_t number_of_compressed_datasources = 0;
if (geometry_datasource_input_stream)
{
@@ -282,12 +354,7 @@ int Storage::Run()
// Load datasource name sizes. This file is optional, and it's non-fatal if it doesn't
// exist
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::ifstream datasource_names_input_stream(datasource_names_path.c_str(), std::ios::binary);
std::vector<char> m_datasource_name_data;
std::vector<std::size_t> m_datasource_name_offsets;
std::vector<std::size_t> m_datasource_name_lengths;
@@ -303,11 +370,11 @@ int Storage::Run()
}
}
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,
m_datasource_name_offsets.size());
m_datasource_name_offsets.size());
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
util::SimpleLogger().Write() << "allocating shared memory of "
@@ -330,7 +397,7 @@ int Storage::Run()
file_index_path_ptr +
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
0);
std::copy(absolute_file_index_path.string().begin(), absolute_file_index_path.string().end(), file_index_path_ptr);
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
// Loading street names
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
@@ -437,7 +504,8 @@ int Storage::Run()
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
{
std::cout << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
std::cout << "Copying "
<< (m_datasource_name_data.end() - m_datasource_name_data.begin())
<< " chars into name data ptr\n";
std::copy(m_datasource_name_data.begin(), m_datasource_name_data.end(),
datasource_name_data_ptr);
@@ -537,15 +605,6 @@ int Storage::Run()
}
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
SharedMemory *data_type_memory =
makeSharedMemory(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
-38
View File
@@ -1,38 +0,0 @@
#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);
}
}
}
+5 -132
View File
@@ -1,14 +1,10 @@
#include "server/server.hpp"
#include "util/routed_options.hpp"
#include "util/make_unique.hpp"
#include "util/simple_logger.hpp"
#include "util/version.hpp"
#include "osrm/osrm.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/storage_config.hpp"
#include <boost/any.hpp>
#include <boost/program_options.hpp>
#ifdef __linux__
#include <sys/mman.h>
@@ -23,7 +19,6 @@
#include <iostream>
#include <new>
#include <thread>
#include <string>
#ifdef _WIN32
boost::function0<void> console_ctrl_function;
@@ -46,111 +41,6 @@ BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
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
{
util::LogPolicy::GetInstance().Unmute();
@@ -160,36 +50,19 @@ int main(int argc, const char *argv[]) try
int ip_port, requested_thread_num;
EngineConfig config;
boost::filesystem::path base_path;
const unsigned init_result = generateServerProgramOptions(
argc, argv, base_path, ip_address, ip_port, requested_thread_num,
const unsigned init_result = util::GenerateServerProgramOptions(
argc, argv, config.server_paths, ip_address, ip_port, requested_thread_num,
config.use_shared_memory, trial_run, config.max_locations_trip,
config.max_locations_viaroute, config.max_locations_distance_table,
config.max_locations_map_matching);
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
if (init_result == util::INIT_OK_DO_NOT_START_ENGINE)
{
return EXIT_SUCCESS;
}
if (init_result == INIT_FAILED)
if (init_result == util::INIT_FAILED)
{
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__
struct MemoryLocker final
+157 -11
View File
@@ -10,7 +10,7 @@
using namespace osrm;
// generate boost::program_options object for the routing part
bool generateDataStoreOptions(const int argc, const char *argv[], boost::filesystem::path& base_path)
bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataPaths &paths)
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
@@ -20,11 +20,36 @@ bool generateDataStoreOptions(const int argc, const char *argv[], boost::filesys
// declare a group of options that will be allowed both on command line
// as well as in a config file
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
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
"base,b", boost::program_options::value<boost::filesystem::path>(&base_path),
"base,b", boost::program_options::value<boost::filesystem::path>(&paths["base"]),
"base path to .osrm file");
// positional option
@@ -68,6 +93,132 @@ bool generateDataStoreOptions(const int argc, const char *argv[], boost::filesys
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;
}
@@ -75,18 +226,13 @@ int main(const int argc, const char *argv[]) try
{
util::LogPolicy::GetInstance().Unmute();
boost::filesystem::path base_path;
if (!generateDataStoreOptions(argc, argv, base_path))
storage::DataPaths paths;
if (!generateDataStoreOptions(argc, argv, paths))
{
return EXIT_SUCCESS;
}
storage::StorageConfig config(base_path);
if (!config.IsValid())
{
util::SimpleLogger().Write(logWARNING) << "Invalid file path given!";
return EXIT_FAILURE;
}
storage::Storage storage(std::move(config));
storage::Storage storage(paths);
return storage.Run();
}
catch (const std::bad_alloc &e)
+14
View File
@@ -29,6 +29,20 @@ Coordinate::Coordinate(const FloatLongitude lon_, const FloatLatitude 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
+18 -80
View File
@@ -4,6 +4,7 @@
#include "util/trigonometry_table.hpp"
#include <boost/assert.hpp>
#include <boost/math/constants/constants.hpp>
#include <cmath>
@@ -13,7 +14,6 @@ namespace osrm
{
namespace util
{
namespace coordinate_calculation
{
@@ -43,11 +43,11 @@ double haversineDistance(const Coordinate coordinate_1, const Coordinate coordin
const double ln1 = lon1 / COORDINATE_PRECISION;
const double lt2 = lat2 / COORDINATE_PRECISION;
const double ln2 = lon2 / COORDINATE_PRECISION;
const double dlat1 = lt1 * DEGREE_TO_RAD;
const double dlat1 = lt1 * (RAD);
const double dlong1 = ln1 * DEGREE_TO_RAD;
const double dlat2 = lt2 * DEGREE_TO_RAD;
const double dlong2 = ln2 * DEGREE_TO_RAD;
const double dlong1 = ln1 * (RAD);
const double dlat2 = lt2 * (RAD);
const double dlong2 = ln2 * (RAD);
const double dlong = dlong1 - dlong2;
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(lon2 != std::numeric_limits<int>::min());
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * DEGREE_TO_RAD;
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
const double y_value = float_lat2 - float_lat1;
@@ -269,84 +269,22 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
namespace mercator
{
FloatLatitude yToLat(const double y)
FloatLatitude yToLat(const double value)
{
const double normalized_lat = RAD_TO_DEGREE * 2. * std::atan(std::exp(y * DEGREE_TO_RAD));
using namespace boost::math::constants;
return FloatLatitude(normalized_lat - 90.);
return FloatLatitude(
180. * (1. / pi<long double>()) *
(2. * std::atan(std::exp(value * pi<double>() / 180.)) - half_pi<double>()));
}
double latToY(const FloatLatitude latitude)
{
const double normalized_lat = 90. + static_cast<double>(latitude);
using namespace boost::math::constants;
return RAD_TO_DEGREE * std::log(std::tan(normalized_lat * DEGREE_TO_RAD * 0.5));
}
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;
return 180. * (1. / pi<double>()) *
std::log(std::tan((pi<double>() / 4.) +
static_cast<double>(latitude) * (pi<double>() / 180.) / 2.));
}
} // ns mercato // ns mercatorr
-62
View File
@@ -1,62 +0,0 @@
#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
-74
View File
@@ -1,74 +0,0 @@
#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()
-1
View File
@@ -103,7 +103,6 @@ class MockDataFacadeT final : public osrm::engine::datafacade::BaseDataFacade<Ed
std::string get_name_for_id(const unsigned /* name_id */) const { return ""; }
std::size_t GetCoreSize() const { return 0; }
std::string GetTimestamp() const { return ""; }
bool GetUTurnsDefault() const override { return true; }
};
using MockDataFacade = MockDataFacadeT<contractor::QueryEdge::EdgeData>;
+13 -14
View File
@@ -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.geometries, result_1->geometries);
BOOST_CHECK_EQUAL(reference_1.overview, result_1->overview);
BOOST_CHECK_EQUAL(reference_1.uturns, result_1->uturns);
CHECK_EQUAL_RANGE(reference_1.uturns, result_1->uturns);
CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
@@ -146,26 +146,25 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_2.alternatives, result_2->alternatives);
BOOST_CHECK_EQUAL(reference_2.geometries, result_2->geometries);
BOOST_CHECK_EQUAL(reference_2.overview, result_2->overview);
BOOST_CHECK_EQUAL(reference_2.uturns, result_2->uturns);
CHECK_EQUAL_RANGE(reference_2.uturns, result_2->uturns);
CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
engine::api::RouteParameters reference_3{false,
false,
engine::api::RouteParameters::GeometriesType::GeoJSON,
engine::api::RouteParameters::OverviewType::False,
true};
std::vector<boost::optional<bool>> uturns_3 = {true, false, boost::none};
engine::api::RouteParameters reference_3{
false, false, engine::api::RouteParameters::GeometriesType::GeoJSON,
engine::api::RouteParameters::OverviewType::False, uturns_3};
reference_3.coordinates = coords_1;
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;");
BOOST_CHECK(result_3);
BOOST_CHECK_EQUAL(reference_3.steps, result_3->steps);
BOOST_CHECK_EQUAL(reference_3.alternatives, result_3->alternatives);
BOOST_CHECK_EQUAL(reference_3.geometries, result_3->geometries);
BOOST_CHECK_EQUAL(reference_3.overview, result_3->overview);
BOOST_CHECK_EQUAL(reference_3.uturns, result_3->uturns);
CHECK_EQUAL_RANGE(reference_3.uturns, result_3->uturns);
CHECK_EQUAL_RANGE(reference_3.bearings, result_3->bearings);
CHECK_EQUAL_RANGE(reference_3.radiuses, result_3->radiuses);
CHECK_EQUAL_RANGE(reference_3.coordinates, result_3->coordinates);
@@ -181,7 +180,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true,
engine::api::RouteParameters::GeometriesType::Polyline,
engine::api::RouteParameters::OverviewType::Simplified,
boost::optional<bool>{},
std::vector<boost::optional<bool>>{},
coords_1,
hints_4,
std::vector<boost::optional<double>>{},
@@ -197,7 +196,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
BOOST_CHECK_EQUAL(reference_4.geometries, result_4->geometries);
BOOST_CHECK_EQUAL(reference_4.overview, result_4->overview);
BOOST_CHECK_EQUAL(reference_4.uturns, result_4->uturns);
CHECK_EQUAL_RANGE(reference_4.uturns, result_4->uturns);
CHECK_EQUAL_RANGE(reference_4.bearings, result_4->bearings);
CHECK_EQUAL_RANGE(reference_4.radiuses, result_4->radiuses);
CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates);
@@ -209,7 +208,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true,
engine::api::RouteParameters::GeometriesType::Polyline,
engine::api::RouteParameters::OverviewType::Simplified,
boost::optional<bool>{},
std::vector<boost::optional<bool>>{},
coords_1,
std::vector<boost::optional<engine::Hint>>{},
std::vector<boost::optional<double>>{},
@@ -221,7 +220,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_5.alternatives, result_5->alternatives);
BOOST_CHECK_EQUAL(reference_5.geometries, result_5->geometries);
BOOST_CHECK_EQUAL(reference_5.overview, result_5->overview);
BOOST_CHECK_EQUAL(reference_5.uturns, result_5->uturns);
CHECK_EQUAL_RANGE(reference_5.uturns, result_5->uturns);
CHECK_EQUAL_RANGE(reference_5.bearings, result_5->bearings);
CHECK_EQUAL_RANGE(reference_5.radiuses, result_5->radiuses);
CHECK_EQUAL_RANGE(reference_5.coordinates, result_5->coordinates);
@@ -239,7 +238,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_6.alternatives, result_6->alternatives);
BOOST_CHECK_EQUAL(reference_6.geometries, result_6->geometries);
BOOST_CHECK_EQUAL(reference_6.overview, result_6->overview);
BOOST_CHECK_EQUAL(reference_6.uturns, result_6->uturns);
CHECK_EQUAL_RANGE(reference_6.uturns, result_6->uturns);
CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
-66
View File
@@ -24,69 +24,3 @@ BOOST_AUTO_TEST_CASE(regression_test_1347)
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);
}
+83
View File
@@ -0,0 +1,83 @@
#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()
-25
View File
@@ -1,25 +0,0 @@
#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()