Compare commits

..

182 Commits

Author SHA1 Message Date
Daniel J. Hofmann e1e76d04d1 Adds round trip tests for RFC 4648 Test Vectors and equality checks 2016-03-23 22:47:22 +01:00
Daniel J. Hofmann 451bbe3021 Makes hint Equatable and Printable for tests 2016-03-23 22:47:22 +01:00
Daniel J. Hofmann 88a76aaecf Make Hint encoding safe for passing them as GET parameter in URLs
Thanks @TheMarex for flagging this!
2016-03-23 22:42:28 +01:00
Daniel J. Hofmann 87428f8fc9 Completely re-write base64 logic, make API suck less in doing so 2016-03-23 22:42:12 +01:00
Daniel J. Hofmann 6c9ddde682 RFC 4648 Test Vectors 2016-03-23 22:41:10 +01:00
Daniel J. Hofmann b4b148e3dc Object Encoder -> Base64, kill false dependencies while doing so 2016-03-23 22:40:59 +01:00
Daniel J. Hofmann 4a84ca3197 Adapts Hint encoding and decoding to new fixed data facade 2016-03-23 22:40:45 +01:00
Daniel J. Hofmann df182ebc38 Formats parameter parser unit tests 2016-03-23 22:40:32 +01:00
Patrick Niklaus c86864976c Fix hint size 2016-03-23 22:36:20 +01:00
Patrick Niklaus c3dd77d32b Always safe the absolute path to .fileIndex 2016-03-23 22:18:11 +01:00
Patrick Niklaus 2357d1c095 Merge pull request #2137 from noblige/rewrite/new-api
fixed compilation error on debian jessie with boost 1.54
2016-03-23 14:35:36 -04:00
Patrick Niklaus 7cd70679f1 Install storage_config.hpp 2016-03-23 19:19:00 +01:00
Aleksei Potov 08c1ac0daf compilation error on debian jessie with boost 1.54 2016-03-23 17:55:56 +00:00
Daniel Patterson 48237b30ea Fix boost geometry constructor.
Versions older than 1.58 don't support the initializer-list form.
2016-03-23 10:47:06 -07:00
Moritz Kobitzsch cac1298864 syncronize geometry and steps after post-processing 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 83e6679d61 added list of intersections to the step-maneuver, not in api so far 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch f3ea86b611 fix initial maneuvers 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch f3de53c363 post processing moved onto route-steps, looses sync with geometry segments 2016-03-23 17:52:51 +01:00
Patrick Niklaus 19434d42b4 Simplify the timestamp handling 2016-03-23 17:52:51 +01:00
Patrick Niklaus ea24ea64f2 Check all streams 2016-03-23 17:52:51 +01:00
Patrick Niklaus 39f5cf1c22 std::string -> boost::filesystem::path 2016-03-23 17:52:51 +01:00
Patrick Niklaus 91384ecd8c Only allow to specify the common base path 2016-03-23 17:52:51 +01:00
Patrick Niklaus 5c28eabbe0 print -> io.write 2016-03-23 17:52:51 +01:00
Patrick Niklaus 42dd45b29b Address PR comments
Renamed lua_function_exists and removes unused print function
2016-03-23 17:52:51 +01:00
Patrick Niklaus 6f4095f23f Use uturn default from .properties file 2016-03-23 17:52:51 +01:00
Patrick Niklaus 9c6c02d85b Adds .properties file to osrm-extract ouput
This file contains global properties set by the lua
profile, such as enabling uturns at vias and penalties.
This file will be consumed by the server.
2016-03-23 17:52:51 +01:00
Patrick Niklaus 47afe60e5f Use global uturns parameter.
Instead of previously per-via settings like uturns=true;false;true;; it
now only supports a global setting uturns=true.
2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 0471ace55d improves consistency of fork handling 2016-03-23 17:52:51 +01:00
Patrick Niklaus 49e2a4ec07 Make gcc 4.8 happy and disable protected because of lambdas 2016-03-23 17:52:51 +01:00
Daniel Patterson 991c5f5d5d Properly clip lines so that we don't get crazy coords with long linestrings (relative to tile coords) 2016-03-23 17:52:51 +01:00
Daniel Patterson 87c77e7d77 Include edge duration information. 2016-03-23 17:52:51 +01:00
Patrick Niklaus 2cf120fc49 Implement viewport code to fix simplification
This fixes #2083
2016-03-23 17:52:51 +01:00
Patrick Niklaus d4eaea1e7d Add tests for coordinate transformation 2016-03-23 17:52:51 +01:00
Patrick Niklaus 51a13675d4 Consolidate math functions 2016-03-23 17:52:51 +01:00
Patrick Niklaus af4cb96aa5 get_name_for_id -> GetNameForID 2016-03-23 17:52:51 +01:00
Patrick Niklaus 439a7ba661 Simplfy name change announcement 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch a0ff0b1258 fix division by zero 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 1cc9a2f4a1 restructured to only return valid turns to the outside + cleanup 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch a3cf7f09e8 less new names, forks consider road classes, api clean-up 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 831a536224 implement basic turn handling 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 7df00683e1 implements relative position feature based on coordinates 2016-03-23 17:52:51 +01:00
Patrick Niklaus 0c0803c77b Don't sum up durations of merged steps since we do that in a different place now 2016-03-23 17:52:51 +01:00
Patrick Niklaus 7c5d56afcb Fix foward/backwad swap 2016-03-23 17:52:51 +01:00
Patrick Niklaus 892b9dff4a Limit zoomlevel to 18 2016-03-23 17:52:51 +01:00
Patrick Niklaus 04a8c1833c Fix shared memory 2016-03-23 17:52:51 +01:00
Patrick Niklaus c217ff815c Fixup for last commit 2016-03-23 17:52:51 +01:00
Daniel Patterson 893c9f7326 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-23 17:52:51 +01:00
Patrick Niklaus 84fa7ae353 Fix ingestion fixed duration values from UnpackPath 2016-03-23 17:52:51 +01:00
Patrick Niklaus bb3256573b Fix durations in UnpackPath 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 96d9ef3951 fixes a broken assertion 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 11572702e9 fix merging of turn instructions 2016-03-23 17:52:51 +01:00
Patrick Niklaus 6d16bb5b25 Include reverse edges again 2016-03-23 17:52:51 +01:00
Patrick Niklaus 89eb2a3778 Formating and logging changes for turn classification 2016-03-23 17:52:51 +01:00
Patrick Niklaus 87408cfd73 Handle case of dead-end edges by inserting an invalid turn 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch dd4066c46e report depart/arrive in addition to waypoint 2016-03-23 17:52:51 +01:00
Patrick Niklaus 3f559211a4 Only install necessary headers 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 5892c6ea09 Adds the license preamble for all publicly installed eaders, closes #2036 2016-03-23 17:52:51 +01:00
Patrick Niklaus dea0063a56 Remove the encoder/decoder dependecy from Hint 2016-03-23 17:52:51 +01:00
Patrick Niklaus eec270968e Rename alternative -> alternatives 2016-03-23 17:52:51 +01:00
Patrick Niklaus 056a7422e0 Remove obsolete debug information 2016-03-23 17:52:51 +01:00
Patrick Niklaus 3d3fea768c Just return NoSegment in map matching if all candidates are empty 2016-03-23 17:52:51 +01:00
Patrick Niklaus 1a6c16fea1 Add failing test for map matching of outlier 2016-03-23 17:52:51 +01:00
Patrick Niklaus 3c56385ba8 Fix missing capitalization of error codes 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 1947671ae3 encapsulated into class 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 3189f24a17 improving fork handling on three-way turns 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch dd5c730a01 fix comparison for ramps on three-way turns 2016-03-23 17:52:51 +01:00
Patrick Niklaus da1dbcfb34 Minor auto iterator cleanup 2016-03-23 17:52:51 +01:00
Patrick Niklaus 8f5091f711 Don't pass down unsnapped coordinates. All information is already there 2016-03-23 17:52:51 +01:00
Patrick Niklaus 0da7302d62 Fix camMergeTrivially 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch f0b40c1948 fixes roundabout counting 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch ecefb4a20e fixes assignment for basic turn types / invalid ramp assignment 2016-03-23 17:52:51 +01:00
Patrick Niklaus 9b1861e017 Add edge id assertions 2016-03-23 17:52:51 +01:00
Patrick Niklaus 4fb041391f 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-23 17:52:51 +01:00
Patrick Niklaus 64cc7d8aac Move bearing to public namespace 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 556223d43b Properly includes needed headers in turn analysis interface 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 0b1e82105e Const-correctnes for compressed geometry iterator 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann c9ad8736b0 Use stdint and using type-alias for discrete angle 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann cded2501a5 Hide functional road classification based on tags in implementation file 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 4d94ec2792 Inline initialize functional road classification hash table 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 7970bc4ad6 256 functional road classes should be enough 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann f84ce976ea Moves route assembly into implementation file 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann ce9a4666f3 Fixes remaining engine/guidance includes 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann ff55b4e001 Fixes accumulate living in <numeric> and not <algorithm> 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 8040af329b Puts step maneuver handling into implementation file 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann b8c059b5c2 Removes penalizing move 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 4e2e2059b1 Uses static_casts for underlying type in post processing 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 922599a8ca Fix asymmetry in min/max from using -max 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 5bc0595591 Adapts MakeResponse to not pass vector by pointer 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 0f600c9262 Fixes multi-line comment 2016-03-23 17:52:51 +01:00
Daniel J. Hofmann 9338d418c8 Runs scripts/format.sh 2016-03-23 17:52:51 +01:00
Patrick Niklaus 4d56b8ff0d Fix coodinate include and unused warnings 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 92b4f14db6 start of four way turns 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch a1f1da4c16 improved fork handling 2016-03-23 17:52:51 +01:00
Patrick Niklaus c337d55d45 Fix crash on extracting Berlin in guidance 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch be5f231641 bugfixing/classification 2016-03-23 17:52:51 +01:00
Patrick Niklaus c19fae4a43 Big Restructuring / Cleanup 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 0831e71438 starting on conflict resolution 2016-03-23 17:52:51 +01:00
Lauren Budorick c44a370dd3 Fixes for gcc compiling, temporary hacks to remove later 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 9f5e79501e handle segregated roads (merge for turn analysis) 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch cf5e722578 structural changes, motorway handling 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch f12bb2fa2f enter and exit roundabout feature - currently not showing turn 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 28d878ed23 migrated out of edge based graph factory 2016-03-23 17:52:51 +01:00
Moritz Kobitzsch 6db16e950a relative waypoint locations 2016-03-23 17:52:14 +01:00
Moritz Kobitzsch 862f8d6ff3 handling of roundabouts (simple version) 2016-03-23 17:52:14 +01:00
Moritz Kobitzsch 8c67dd4504 advanced guidance on 5.0 2016-03-23 17:52:14 +01:00
Patrick Niklaus 23d79bde54 Fix numerical problems with polyline 2016-03-23 17:50:13 +01:00
Patrick Niklaus 410d561b4c Fix table response format to return null + double in seconds 2016-03-23 17:50:13 +01:00
Patrick Niklaus 8ab38b126c Return NoMatch 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann c13f1aa89d Provides ctor from base path for EngineConfig, fixes #2030 2016-03-23 17:50:13 +01:00
Patrick Niklaus b4bf0ec5fe Add support for tile plugin 2016-03-23 17:50:13 +01:00
Patrick Niklaus f7b7dbf51a Preliminary integration of the tile plugin 2016-03-23 17:50:13 +01:00
Patrick Niklaus 41c9f94e5f sources and destinations can be empty actually 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 77adbca138 Fixes coordinate, source and destination validation by means of backporting #2041 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann f3e06b41dd Fixes ownership semantics and forwarding references misplacements in the JSON factory 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann ee4b8618f8 Unwrap function call from identity lambda 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 58973a4fd1 Uses JSON's String constructor for polyline encoding 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 4b8017d412 Passes coordinates by value 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 64d4d58a0d Asserts on unknown TurnInstruction 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 5d83fa1e4c Fixes header includes in the JSON factory 2016-03-23 17:50:13 +01:00
Dane Springmeyer 7a6aa6f1a7 fix compile of osrm-components 2016-03-23 17:50:13 +01:00
Patrick Niklaus e5d964492a Fix if the last coordinate is not found 2016-03-23 17:50:13 +01:00
Patrick Niklaus bb2baa82aa Allocate correct table size 2016-03-23 17:50:13 +01:00
Patrick Niklaus 0b5875a412 Fix travel mode passing from profiles up to the API 2016-03-23 17:50:13 +01:00
Patrick Niklaus 9a2b8cb16d Fix geometries type in steps 2016-03-23 17:50:13 +01:00
Patrick Niklaus 5fb6db7a9a Fix table parameter parsing 2016-03-23 17:50:13 +01:00
Patrick Niklaus c1647c99c8 Fix behaviour of table if sources/destinations arrays are empty 2016-03-23 17:50:13 +01:00
Patrick Niklaus 39d6c33b32 Fuck. this. shit. 2016-03-23 17:50:13 +01:00
Patrick Niklaus 9b75f618e8 Change stream operator of strong typedef 2016-03-23 17:50:13 +01:00
Patrick Niklaus 225049ffa7 Fix stream operator for coordinate 2016-03-23 17:50:13 +01:00
Patrick Niklaus 2df832a95e Add stream operator to Rectangle 2016-03-23 17:50:13 +01:00
Patrick Niklaus 75912b3662 Add euclideanDistance to coordinate_calculation 2016-03-23 17:50:13 +01:00
Patrick Niklaus c9a19c954e Simplify static_rtree tests 2016-03-23 17:50:13 +01:00
Patrick Niklaus 9a19086926 First round of lat,lng -> lng,lat switcheroo 2016-03-23 17:50:13 +01:00
Patrick Niklaus 90e8a3e1dc Add rectangle unit test 2016-03-23 17:50:13 +01:00
Patrick Niklaus 0270ee59b4 Fix match and trip API response 2016-03-23 17:50:13 +01:00
Patrick Niklaus 5728af4a2a Fix out-of-bounds write in map_matching 2016-03-23 17:50:13 +01:00
Dane Springmeyer 6cf19ac4cf Fix compile on OS X 2016-03-23 17:50:13 +01:00
Patrick Niklaus 3f81f6b441 Finish the nearest plugin 2016-03-23 17:50:13 +01:00
Patrick Niklaus 669aa9e672 Initialize NearestParameters correctly 2016-03-23 17:50:13 +01:00
Patrick Niklaus 1d3afd5c38 Adapt to feedback in #519 2016-03-23 17:50:13 +01:00
Patrick Niklaus c53a448589 Add trip plugin 2016-03-23 17:50:13 +01:00
Patrick Niklaus cb82376083 Hook up map matching 2016-03-23 17:50:13 +01:00
Patrick Niklaus 9d10490613 First compiling version of map_match plugin 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 1cc7d3ddfb Adapts example/example.cpp to new osrm api 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann aad3d8aa1e Install _all_ transitively from public headers included header 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 9258791811 Fix missing headers in hint.hpp 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 19d5912a93 Adds $prefix/include/osrm to include dirs so that transitive header includes without osrm prefix can be found 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann a4770feac4 Adapt the example to include all osrm public headers 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann c8c6f8c2e7 Fixes missing public header installations 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann d7f9c31d0b Fix forward declarations in publicly facing osrm header 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 44b802c053 Enable all plugins with aStatus::Error return code fallback for not implemented ones 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 99f18051f6 Adds publicly facing alias headers for parameters 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 99f94969aa Temporarily comment out match.cpp as to not break the build process 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann bc6d5bbde2 We don't need templates at all, this is not CRTP? 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 6aa5ab5904 Fix classes for service member function definitions 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 0c64503218 Service skeletons for nearest, trip, match 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann e15ba88c0b Fix grammar constraint and enable all plugin links 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 2f9d1d3db2 Plugin grammar skeletons 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 42e6e974ac Enforce parameter and grammar type to catch subtle bugs 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 5a97e7a7ce Link parameters to grammars 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 8c54794d5a Require a BaseParameters type at compile time via enable_if 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann e377a19c10 Adapts Nearest plugin to new API 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 0fb6e9bf3f Fix deleting incomplete type and make Engine moveable only 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann d6a8690425 Adapts publicly facing new API 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann cc65446785 Adapts NearestParameters to new API 2016-03-23 17:50:13 +01:00
Patrick Niklaus 487df70eb3 Initial non-building match plugin 2016-03-23 17:50:13 +01:00
Lauren Budorick aa79c41804 Include numeric in assemble_overview.cpp (needed on OSX for std::accumulate) 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 7faadb1233 Semantic action handler requires passing optional by value and fusion::vector2 2016-03-23 17:50:13 +01:00
Patrick Niklaus 5c8a895471 Add tests for bearing parsing 2016-03-23 17:50:13 +01:00
Patrick Niklaus e932a8253a Add table service 2016-03-23 17:50:13 +01:00
Patrick Niklaus 84097964b7 Add table API 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann c2a35b35ad Optional<T> semantic action handler takes T argument 2016-03-23 17:50:13 +01:00
Patrick Niklaus f6612e2afa Fix parameter parsing tests 2016-03-23 17:50:13 +01:00
Patrick Niklaus 09378f28fd Fix table plugin 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 01ddfbcba3 First take at distance table API re-write 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann 0468d7a7c5 Adapts TableParameters and its validation to new API 2016-03-23 17:50:13 +01:00
Patrick Niklaus 39bc0fd330 Add viaroute suport for new API 2016-03-23 17:50:13 +01:00
Patrick Niklaus 53dbb1eac2 Also exclude the compressed flag from the data format 2016-03-23 17:50:13 +01:00
Patrick Niklaus f5bc843fe6 Remove geometry indicator 2016-03-23 17:50:13 +01:00
Daniel J. Hofmann c78dff9a15 Write out unsigned with a check for edge counter overflow 2016-03-19 00:27:55 +01:00
Daniel J. Hofmann 25fea558ba Fixes the edge-based-graph factory's edge counter serialization.
The counter for original edges is of type `std::size_t`, but we
serialized `sizeof(unsigned)` number of bytes out to the `.osrm.edges`
file.

We should probably check all writes (analogous for reads) and make the
count parameter dependent on `sizeof(variable)`.

    ag '\.write\((.*), sizeof\((.*)\)\);'
2016-03-19 00:27:55 +01:00
Daniel J. Hofmann b1c84b598f Print the _local_ endpoint Boost ASIO assigns a port to, fixes #2097 2016-03-18 12:09:28 +01:00
93 changed files with 4188 additions and 3132 deletions
+4 -2
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>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
add_library(osrm_extract $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_contract $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
@@ -94,6 +94,7 @@ add_executable(server-tests EXCLUDE_FROM_ALL unit_tests/server_tests.cpp ${Serve
# Benchmarks
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)
@@ -381,9 +382,10 @@ set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp incl
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp)
set(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)
+2 -1
View File
@@ -29,7 +29,8 @@ 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{argv[1]};
EngineConfig config;
config.storage_config = {argv[1]};
config.use_shared_memory = false;
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
+202
View File
@@ -0,0 +1,202 @@
@routing @guidance
Feature: Basic Roundabout
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Scenario: Ramp Exit Right
Given the node map
| a | b | c | d | e |
| | | | f | g |
And the ways
| nodes | highway |
| abcde | motorway |
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive |
Scenario: Ramp Exit Right Curved Right
Given the node map
| a | b | c | | |
| | | f | d | |
| | | | g | e |
And the ways
| nodes | highway |
| abcde | motorway |
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive |
Scenario: Ramp Exit Right Curved Left
Given the node map
| | | | | e |
| | | | d | g |
| a | b | c | f | |
And the ways
| nodes | highway |
| abcde | motorway |
| cfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, cfg, cfg | depart, ramp-slight-right, arrive |
Scenario: Ramp Exit Left
Given the node map
| | | | f | g |
| a | b | c | d | e |
And the ways
| nodes | highway |
| abcde | motorway |
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive |
Scenario: Ramp Exit Left Curved Left
Given the node map
| | | | g | e |
| | | f | d | |
| a | b | c | | |
And the ways
| nodes | highway |
| abcde | motorway |
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive |
Scenario: Ramp Exit Left Curved Right
Given the node map
| a | b | c | f | |
| | | | d | g |
| | | | | e |
And the ways
| nodes | highway |
| abcde | motorway |
| cfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| a,g | abcde, cfg, cfg | depart, ramp-slight-left, arrive |
Scenario: On Ramp Right
Given the node map
| a | b | c | d | e |
| f | g | | | |
And the ways
| nodes | highway |
| abcde | motorway |
| fgd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| f,e | abcde, fgd, fgd | depart, merge-slight-left, arrive |
Scenario: On Ramp Left
Given the node map
| f | g | | | |
| a | b | c | d | e |
And the ways
| nodes | highway |
| abcde | motorway |
| fgd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| f,e | abcde, fgd, fgd | depart, merge-slight-right, arrive |
Scenario: Highway Fork
Given the node map
| | | | | d | e |
| a | b | c | | | |
| | | | | f | g |
And the ways
| nodes | highway |
| abcde | motorway |
| cfg | motorway |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde, abcde | depart, fork-left, arrive |
| a,g | abcde, cfg, cfg | depart, fork-right, arrive |
Scenario: Fork After Ramp
Given the node map
| | | | | d | e |
| a | b | c | | | |
| | | | | f | g |
And the ways
| nodes | highway |
| abc | motorway_link |
| cde | motorway |
| cfg | motorway |
When I route I should get
| waypoints | route | turns |
| a,e | abc, cde, cde | depart, fork-left, arrive |
| a,g | abc, cfg, cfg | depart, fork-right, arrive |
Scenario: On And Off Ramp Right
Given the node map
| a | b | | c | | d | e |
| f | g | | | | h | i |
And the ways
| nodes | highway |
| abcde | motorway |
| fgc | motorway_link |
| chi | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| f,e | fgc, abcde, abcde | depart, merge-slight-left, arrive |
| a,i | abcde, chi, chi | depart, ramp-slight-right, arrive |
| f,i | fgc, chi, chi | depart, turn-slight-right, arrive |
Scenario: On And Off Ramp Left
Given the node map
| f | g | | | | h | i |
| a | b | | c | | d | e |
And the ways
| nodes | highway |
| abcde | motorway |
| fgc | motorway_link |
| chi | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde, abcde | depart, arrive |
| f,e | fgc, abcde, abcde | depart, merge-slight-right, arrive |
| a,i | abcde, chi, chi | depart, ramp-slight-left, arrive |
| f,i | fgc, chi, chi | depart, turn-slight-left, arrive |
+173
View File
@@ -0,0 +1,173 @@
@routing @guidance
Feature: Basic Roundabout
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Scenario: Enter and Exit
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | no |
| cd | no |
| ef | no |
| gh | no |
| bcegb | yes |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart, roundabout-exit-1, arrive |
| a,f | ab,ef,ef | depart, roundabout-exit-2, arrive |
| a,h | ab,gh,gh | depart, roundabout-exit-3, arrive |
| d,f | cd,ef,ef | depart, roundabout-exit-1, arrive |
| d,h | cd,gh,gh | depart, roundabout-exit-2, arrive |
| d,a | cd,ab,ab | depart, roundabout-exit-3, arrive |
| f,h | ef,gh,gh | depart, roundabout-exit-1, arrive |
| f,a | ef,ab,ab | depart, roundabout-exit-2, arrive |
| f,d | ef,cd,cd | depart, roundabout-exit-3, arrive |
| h,a | gh,ab,ab | depart, roundabout-exit-1, arrive |
| h,d | gh,cd,cd | depart, roundabout-exit-2, arrive |
| h,f | gh,ef,ef | depart, roundabout-exit-3, arrive |
Scenario: Only Enter
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | no |
| cd | no |
| ef | no |
| gh | no |
| bcegb | yes |
When I route I should get
| waypoints | route | turns |
| a,b | ab,ab | depart, arrive |
| a,c | ab,bcegb | depart, roundabout-enter, arrive |
| a,e | ab,bcegb | depart, roundabout-enter, arrive |
| a,g | ab,bcegb | depart, roundabout-enter, arrive |
| d,c | cd,cd | depart, arrive |
| d,e | cd,bcegb | depart, roundabout-enter, arrive |
| d,g | cd,bcegb | depart, roundabout-enter, arrive |
| d,b | cd,bcegb | depart, roundabout-enter, arrive |
| f,e | ef,ef | depart, arrive |
| f,g | ef,bcegb | depart, roundabout-enter, arrive |
| f,b | ef,bcegb | depart, roundabout-enter, arrive |
| f,c | ef,bcegb | depart, roundabout-enter, arrive |
| h,g | gh,gh | depart, arrive |
| h,b | gh,bcegb | depart, roundabout-enter, arrive |
| h,c | gh,bcegb | depart, roundabout-enter, arrive |
| h,e | gh,bcegb | depart, roundabout-enter, arrive |
Scenario: Only Exit
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | no |
| cd | no |
| ef | no |
| gh | no |
| bcegb | yes |
When I route I should get
| waypoints | route | turns |
| b,a | ab,ab | depart, arrive |
| b,d | bcegb,cd,cd | depart, roundabout-exit-1, arrive |
| b,f | bcegb,ef,ef | depart, roundabout-exit-2, arrive |
| b,h | bcegb,gh,gh | depart, roundabout-exit-3, arrive |
| c,d | cd,cd | depart, arrive |
| c,f | bcegb,ef,ef | depart, roundabout-exit-1, arrive |
| c,h | bcegb,gh,gh | depart, roundabout-exit-2, arrive |
| c,a | bcegb,ab,ab | depart, roundabout-exit-3, arrive |
| e,f | ef,ef | depart, arrive |
| e,h | bcegb,gh,gh | depart, roundabout-exit-1, arrive |
| e,a | bcegb,ab,ab | depart, roundabout-exit-2, arrive |
| e,d | bcegb,cd,cd | depart, roundabout-exit-3, arrive |
| g,h | gh,gh | depart, arrive |
| g,a | bcegb,ab,ab | depart, roundabout-exit-1, arrive |
| g,d | bcegb,cd,cd | depart, roundabout-exit-2, arrive |
| g,f | bcegb,ef,ef | depart, roundabout-exit-3, arrive |
Scenario: Drive Around
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | roundabout |
| ab | no |
| cd | no |
| ef | no |
| gh | no |
| bcegb | yes |
When I route I should get
| waypoints | route | turns |
| b,c | bcegb,bcegb | depart, arrive |
| b,e | bcegb,bcegb | depart, arrive |
| b,g | bcegb,bcegb | depart, arrive |
| c,e | bcegb,bcegb | depart, arrive |
| c,g | bcegb,bcegb | depart, arrive |
| c,b | bcegb,bcegb | depart, arrive |
| e,g | bcegb,bcegb | depart, arrive |
| e,b | bcegb,bcegb | depart, arrive |
| e,c | bcegb,bcegb | depart, arrive |
| g,b | bcegb,bcegb | depart, arrive |
| g,c | bcegb,bcegb | depart, arrive |
| g,e | bcegb,bcegb | depart, arrive |
Scenario: Mixed Entry and Exit
Given the node map
| | a | | c | |
| l | | b | | d |
| | k | | e | |
| j | | h | | f |
| | i | | g | |
And the ways
| nodes | roundabout | oneway |
| abc | no | yes |
| def | no | yes |
| ghi | no | yes |
| jkl | no | yes |
| behkb | yes | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart, roundabout-exit-1, arrive |
| a,f | abc,def,def | depart, roundabout-exit-2, arrive |
| a,i | abc,ghi,ghi | depart, roundabout-exit-3, arrive |
| a,l | abc,jkl,jkl | depart, roundabout-exit-4, arrive |
| d,f | def,def,def | depart, roundabout-exit-1, arrive |
| d,i | def,ghi,ghi | depart, roundabout-exit-2, arrive |
| d,l | def,jkl,jkl | depart, roundabout-exit-3, arrive |
| d,c | def,abc,abc | depart, roundabout-exit-4, arrive |
| g,i | ghi,ghi,ghi | depart, roundabout-exit-1, arrive |
| g,l | ghi,jkl,jkl | depart, roundabout-exit-2, arrive |
| g,c | ghi,abc,abc | depart, roundabout-exit-3, arrive |
| g,f | ghi,edf,edf | depart, roundabout-exit-4, arrive |
| j,l | jkl,jkl,jkl | depart, roundabout-exit-1, arrive |
| j,c | jkl,abc,abc | depart, roundabout-exit-2, arrive |
| j,f | jkl,def,def | depart, roundabout-exit-3, arrive |
| j,i | jkl,ghi,ghi | depart, roundabout-exit-4, arrive |
+12 -12
View File
@@ -8,6 +8,7 @@
#include "engine/hint.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <vector>
@@ -33,24 +34,23 @@ class BaseAPI
util::json::Array waypoints;
waypoints.values.resize(parameters.coordinates.size());
waypoints.values[0] = MakeWaypoint(parameters.coordinates.front(),
segment_end_coordinates.front().source_phantom);
waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
auto coord_iter = std::next(parameters.coordinates.begin());
auto out_iter = std::next(waypoints.values.begin());
for (const auto &phantoms : segment_end_coordinates)
{
*out_iter++ = MakeWaypoint(*coord_iter++, phantoms.target_phantom);
}
boost::range::transform(segment_end_coordinates, out_iter,
[this](const PhantomNodes &phantom_pair)
{
return MakeWaypoint(phantom_pair.target_phantom);
});
return waypoints;
}
protected:
util::json::Object MakeWaypoint(const util::Coordinate input_coordinate,
const PhantomNode &phantom) const
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
util::json::Object MakeWaypoint(const PhantomNode &phantom) const
{
return json::makeWaypoint(phantom.location, facade.get_name_for_id(phantom.name_id),
Hint{input_coordinate, phantom, facade.GetCheckSum()});
return json::makeWaypoint(phantom.location, facade.GetNameForID(phantom.name_id),
Hint{phantom, facade.GetCheckSum()});
}
const datafacade::BaseDataFacade &facade;
+4 -2
View File
@@ -48,7 +48,9 @@ class MatchAPI final : public RouteAPI
response.values["code"] = "ok";
}
protected:
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
// FIXME this logic is a little backwards. We should change the output format of the
// map_matching
// routing algorithm to be easier to consume here.
@@ -98,7 +100,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(parameters.coordinates[trace_index], phantom);
auto waypoint = BaseAPI::MakeWaypoint(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));
+1 -2
View File
@@ -38,8 +38,7 @@ class NearestAPI final : public BaseAPI
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance)
{
auto waypoint = MakeWaypoint(parameters.coordinates.front(),
phantom_with_distance.phantom_node);
auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance;
return waypoint;
});
+34 -6
View File
@@ -57,7 +57,8 @@ class RouteAPI : public BaseAPI
response.values["code"] = "ok";
}
protected:
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
template <typename ForwardIter>
util::json::Value MakeGeometry(ForwardIter begin, ForwardIter end) const
{
@@ -71,7 +72,7 @@ class RouteAPI : public BaseAPI
}
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
std::vector<std::vector<PathData>> unpacked_path_segments,
const std::vector<std::vector<PathData>> &unpacked_path_segments,
const std::vector<bool> &source_traversed_in_reverse,
const std::vector<bool> &target_traversed_in_reverse) const
{
@@ -81,7 +82,6 @@ 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,19 +93,47 @@ 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.source_phantom, phantoms.target_phantom,
reversed_source, reversed_target);
phantoms.target_phantom, reversed_target);
if (parameters.steps)
{
leg.steps = guidance::assembleSteps(
auto 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)
+4 -5
View File
@@ -60,10 +60,10 @@ struct RouteParameters : public BaseParameters
const bool alternatives_,
const GeometriesType geometries_,
const OverviewType overview_,
std::vector<boost::optional<bool>> uturns_,
const boost::optional<bool> uturns_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
geometries{geometries_}, overview{overview_}, uturns{std::move(uturns_)}
geometries{geometries_}, overview{overview_}, uturns{uturns_}
{
}
@@ -71,12 +71,11 @@ struct RouteParameters : public BaseParameters
bool alternatives = true;
GeometriesType geometries = GeometriesType::Polyline;
OverviewType overview = OverviewType::Simplified;
std::vector<boost::optional<bool>> uturns;
boost::optional<bool> uturns;
bool IsValid() const
{
return coordinates.size() >= 2 && BaseParameters::IsValid() &&
(uturns.empty() || uturns.size() == coordinates.size());
return coordinates.size() >= 2 && BaseParameters::IsValid();
}
};
}
+16 -14
View File
@@ -17,6 +17,8 @@
#include "util/integer_range.hpp"
#include <boost/range/algorithm/transform.hpp>
namespace osrm
{
namespace engine
@@ -66,19 +68,19 @@ class TableAPI final : public BaseAPI
response.values["code"] = "ok";
}
protected:
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
virtual util::json::Array MakeWaypoints(const std::vector<PhantomNode> &phantoms) const
{
util::json::Array json_waypoints;
json_waypoints.values.reserve(phantoms.size());
BOOST_ASSERT(phantoms.size() == parameters.coordinates.size());
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));
}
boost::range::transform(phantoms, std::back_inserter(json_waypoints.values),
[this](const PhantomNode &phantom)
{
return BaseAPI::MakeWaypoint(phantom);
});
return json_waypoints;
}
@@ -87,12 +89,12 @@ class TableAPI final : public BaseAPI
{
util::json::Array json_waypoints;
json_waypoints.values.reserve(indices.size());
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]));
}
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]);
});
return json_waypoints;
}
+8 -7
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,7 +47,9 @@ class TripAPI final : public RouteAPI
response.values["code"] = "ok";
}
protected:
// FIXME gcc 4.8 doesn't support for lambdas to call protected member functions
// protected:
// FIXME this logic is a little backwards. We should change the output format of the
// trip plugin routing algorithm to be easier to consume here.
util::json::Array MakeWaypoints(const std::vector<std::vector<NodeID>> &sub_trips,
@@ -90,8 +92,7 @@ class TripAPI final : public RouteAPI
auto trip_index = input_idx_to_trip_idx[input_index];
BOOST_ASSERT(!trip_index.NotUsed());
auto waypoint =
BaseAPI::MakeWaypoint(parameters.coordinates[input_index], phantoms[input_index]);
auto waypoint = BaseAPI::MakeWaypoint(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
@@ -0,0 +1,126 @@
#ifndef OSRM_BASE64_HPP
#define OSRM_BASE64_HPP
#include <string>
#include <iterator>
#include <type_traits>
#include <cstddef>
#include <climits>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/range/algorithm/copy.hpp>
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
// See: https://tools.ietf.org/html/rfc4648
// Implementation adapted from: http://stackoverflow.com/a/28471421
// The C++ standard guarantees none of this by default, but we need it in the following.
static_assert(CHAR_BIT == 8u, "we assume a byte holds 8 bits");
static_assert(sizeof(char) == 1u, "we assume a char is one byte large");
namespace osrm
{
namespace engine
{
// Encoding Implementation
// Encodes a chunk of memory to Base64.
inline std::string encodeBase64(const unsigned char *first, std::size_t size)
{
using namespace boost::archive::iterators;
const std::string bytes{first, first + size};
using Iter = base64_from_binary<transform_width<std::string::const_iterator, 6, 8>>;
Iter view_first{begin(bytes)};
Iter view_last{end(bytes)};
std::string encoded{view_first, view_last};
return encoded.append((3 - size % 3) % 3, '=');
}
// C++11 standard 3.9.1/1: Plain char, signed char, and unsigned char are three distinct types
// Overload for signed char catches (not only but also) C-string literals.
inline std::string encodeBase64(const signed char *first, std::size_t size)
{
return encodeBase64(reinterpret_cast<const unsigned char *>(first), size);
}
// Overload for char catches (not only but also) C-string literals.
inline std::string encodeBase64(const char *first, std::size_t size)
{
return encodeBase64(reinterpret_cast<const unsigned char *>(first), size);
}
// Convenience specialization, encoding from string instead of byte-dumping it.
inline std::string encodeBase64(const std::string &x) { return encodeBase64(x.data(), x.size()); }
// Encode any sufficiently trivial object to Base64.
template <typename T> std::string encodeBase64Bytewise(const T &x)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
return encodeBase64(reinterpret_cast<const unsigned char *>(&x), sizeof(T));
}
// Decoding Implementation
// Decodes into a chunk of memory that is at least as large as the input.
template <typename OutputIter> void decodeBase64(const std::string &encoded, OutputIter out)
{
using namespace boost::archive::iterators;
using namespace boost::algorithm;
using Iter = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
Iter view_first{begin(encoded)};
Iter view_last{end(encoded)};
const auto null = [](const unsigned char c)
{
return c == '\0';
};
const auto bytes = trim_right_copy_if(std::string{view_first, view_last}, null);
boost::copy(bytes, out);
}
// Convenience specialization, filling string instead of byte-dumping into it.
inline std::string decodeBase64(const std::string &encoded)
{
std::string rv;
decodeBase64(encoded, std::back_inserter(rv));
return rv;
}
// Decodes from Base 64 to any sufficiently trivial object.
template <typename T> T decodeBase64Bytewise(const std::string &encoded)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
T x;
decodeBase64(encoded, reinterpret_cast<unsigned char *>(&x));
return x;
}
} // ns engine
} // ns osrm
#endif /* OSRM_BASE64_HPP */
@@ -138,11 +138,13 @@ class BaseDataFacade
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
virtual std::string get_name_for_id(const unsigned name_id) const = 0;
virtual std::string GetNameForID(const unsigned name_id) const = 0;
virtual std::size_t GetCoreSize() const = 0;
virtual std::string GetTimestamp() const = 0;
virtual bool GetUTurnsDefault() const = 0;
};
}
}
@@ -9,6 +9,7 @@
#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"
@@ -79,6 +80,7 @@ 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;
@@ -86,26 +88,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)
{
if (boost::filesystem::exists(timestamp_path))
util::SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestamp_stream(timestamp_path);
if (!timestamp_stream)
{
util::SimpleLogger().Write() << "Loading Timestamp";
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);
throw util::exception("Could not open " + timestamp_path.string() + " for reading.");
}
getline(timestamp_stream, m_timestamp);
}
void LoadGraph(const boost::filesystem::path &hsgr_path)
@@ -218,28 +220,33 @@ class InternalDataFacade final : public BaseDataFacade
void LoadDatasourceInfo(const boost::filesystem::path &datasource_names_file,
const boost::filesystem::path &datasource_indexes_file)
{
std::ifstream datasources_stream(datasource_indexes_file.c_str(), std::ios::binary);
if (datasources_stream)
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
if (!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));
}
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::ifstream datasourcenames_stream(datasource_names_file.c_str(), std::ios::binary);
if (datasourcenames_stream)
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
if (!datasourcenames_stream)
{
std::string name;
while (std::getline(datasourcenames_stream, name))
{
m_datasource_names.push_back(name);
}
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));
}
}
@@ -276,52 +283,35 @@ class InternalDataFacade final : public BaseDataFacade
m_geospatial_query.reset();
}
explicit InternalDataFacade(
const std::unordered_map<std::string, boost::filesystem::path> &server_paths)
explicit InternalDataFacade(const storage::StorageConfig& config)
{
// 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");
ram_index_path = config.ram_index_path;
file_index_path = config.file_index_path;
util::SimpleLogger().Write() << "loading graph data";
LoadGraph(file_for("hsgrdata"));
LoadGraph(config.hsgr_data_path);
util::SimpleLogger().Write() << "loading edge information";
LoadNodeAndEdgeInformation(file_for("nodesdata"), file_for("edgesdata"));
LoadNodeAndEdgeInformation(config.nodes_data_path, config.edges_data_path);
util::SimpleLogger().Write() << "loading core information";
LoadCoreInformation(file_for("coredata"));
LoadCoreInformation(config.core_data_path);
util::SimpleLogger().Write() << "loading geometries";
LoadGeometries(file_for("geometries"));
LoadGeometries(config.geometries_path);
util::SimpleLogger().Write() << "loading datasource info";
LoadDatasourceInfo(optional_file_for("datasource_names"),
optional_file_for("datasource_indexes"));
LoadDatasourceInfo(config.datasource_names_path,
config.datasource_indexes_path);
util::SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(file_for("timestamp"));
LoadTimestamp(config.timestamp_path);
util::SimpleLogger().Write() << "loading profile properties";
LoadProfileProperties(config.properties_path);
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(file_for("namesdata"));
LoadStreetNames(config.names_data_path);
}
// search graph access
@@ -551,7 +541,7 @@ class InternalDataFacade final : public BaseDataFacade
return m_name_ID_list.at(id);
}
std::string get_name_for_id(const unsigned name_id) const override final
std::string GetNameForID(const unsigned name_id) const override final
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
@@ -652,16 +642,14 @@ class InternalDataFacade final : public BaseDataFacade
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
{
if (m_datasource_names.empty() || datasource_name_id > m_datasource_names.size())
{
if (datasource_name_id == 0)
return "lua profile";
return "UNKNOWN";
}
BOOST_ASSERT(m_datasource_names.size() >= 1);
BOOST_ASSERT(m_datasource_names.size() > datasource_name_id);
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; }
};
}
}
+16 -10
View File
@@ -8,6 +8,7 @@
#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"
@@ -68,6 +69,7 @@ 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;
@@ -98,6 +100,12 @@ 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 =
@@ -343,6 +351,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadViaNodeList();
LoadNames();
LoadCoreInformation();
LoadProfileProperties();
util::SimpleLogger().Write() << "number of geometries: "
<< m_coordinate_list->size();
@@ -621,7 +630,7 @@ class SharedDataFacade final : public BaseDataFacade
return m_name_ID_list.at(id);
}
std::string get_name_for_id(const unsigned name_id) const override final
std::string GetNameForID(const unsigned name_id) const override final
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
@@ -684,16 +693,11 @@ 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;
if (m_datasource_name_offsets.empty() ||
datasource_name_id > m_datasource_name_offsets.size())
{
if (datasource_name_id == 0)
return "lua profile";
return "UNKNOWN";
}
result.reserve(m_datasource_name_lengths[datasource_name_id]);
std::copy(m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id],
m_datasource_name_data.begin() + m_datasource_name_offsets[datasource_name_id] +
m_datasource_name_lengths[datasource_name_id],
@@ -703,6 +707,8 @@ 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; }
};
}
}
+4 -18
View File
@@ -28,9 +28,10 @@ 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
@@ -41,24 +42,9 @@ namespace engine
struct EngineConfig
{
EngineConfig() = default;
bool IsValid() const;
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;
storage::StorageConfig storage_config;
int max_locations_trip = -1;
int max_locations_viaroute = -1;
int max_locations_distance_table = -1;
+12 -8
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,10 +393,14 @@ 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},
current_perpendicular_distance};
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
forward_weight,
forward_offset,
reverse_weight,
reverse_offset,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
return transformed;
}
@@ -51,7 +51,8 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
current_distance +=
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
if (!isSilent(path_point.turn_instruction))
// all changes to this check have to be matched with assemble_steps
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
{
geometry.segment_distances.push_back(current_distance);
geometry.segment_offsets.push_back(geometry.locations.size());
+7 -17
View File
@@ -96,18 +96,12 @@ 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.GetReverseWeightPlusOffset()
: target_node.GetForwardWeightPlusOffset()) /
(target_traversed_in_reverse ? target_node.reverse_weight
: target_node.forward_weight) /
10.;
auto distance = std::accumulate(leg_geometry.segment_distances.begin(),
@@ -136,25 +130,21 @@ RouteLeg assembleLeg(const DataFacadeT &facade,
// The phantom node of t will contain:
// `forward_weight`: duration of (d,t)
// `forward_offset`: duration of (c, d)
//
// 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;
// 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;
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.get_name_for_id(summary_array.front()),
facade.GetNameForID(summary_array.front()),
[&facade](std::string previous, const std::uint32_t name_id)
{
if (name_id != 0)
{
previous += ", " + facade.get_name_for_id(name_id);
previous += ", " + facade.GetNameForID(name_id);
}
return previous;
});
+65 -33
View File
@@ -25,10 +25,13 @@ namespace guidance
namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const WaypointType waypoint_type,
const LegGeometry &leg_geometry,
const std::size_t segment_index,
const unsigned exit);
const std::size_t segment_index);
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const WaypointType waypoint_type,
const LegGeometry &leg_geometry);
} // ns detail
template <typename DataFacadeT>
@@ -40,13 +43,14 @@ 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.forward_weight : source_node.reverse_weight;
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
: source_node.forward_travel_mode;
const EdgeWeight target_duration =
target_traversed_in_reverse ? target_node.forward_weight : target_node.reverse_weight;
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
: target_node.forward_travel_mode;
@@ -56,10 +60,18 @@ 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 =
leg_geometry.locations.size() >= 3
distance_to_start >= MINIMAL_RELATIVE_DISTANCE &&
distance_to_start <= MAXIMAL_RELATIVE_DISTANCE
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
leg_geometry.locations[0], leg_geometry.locations[1], leg_geometry.locations[2]))
source_node.input_location, leg_geometry.locations[0], leg_geometry.locations[1]))
: extractor::guidance::DirectionModifier::UTurn;
if (leg_data.size() > 0)
@@ -68,7 +80,8 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry, segment_index, INVALID_EXIT_NR);
WaypointType::Depart, leg_geometry);
maneuver.location = source_node.location;
// PathData saves the information we need of the segment _before_ the turn,
// but a RouteStep is with regard to the segment after the turn.
@@ -79,18 +92,22 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
{
segment_duration += path_point.duration_until_turn;
if (path_point.turn_instruction != extractor::guidance::TurnInstruction::NO_TURN())
// all changes to this check have to be matched with assemble_geometry
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
{
BOOST_ASSERT(segment_duration >= 0);
const auto name = facade.get_name_for_id(path_point.name_id);
const auto name = facade.GetNameForID(path_point.name_id);
const auto distance = leg_geometry.segment_distances[segment_index];
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,
WaypointType::None, leg_geometry,
segment_index, path_point.exit);
leg_geometry, segment_index);
segment_index++;
segment_duration = 0;
}
@@ -98,8 +115,12 @@ 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.get_name_for_id(target_node.name_id),
duration / 10., distance, target_mode, maneuver,
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id),
duration / 10.,
distance,
target_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
}
@@ -112,35 +133,46 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |---| source_duration
// |---------| target_duration
StepManeuver maneuver = {source_node.location, 0., 0.,
extractor::guidance::TurnInstruction{
extractor::guidance::TurnType::NoTurn, initial_modifier},
WaypointType::Depart, INVALID_EXIT_NR};
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry);
int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0);
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),
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),
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 =
leg_geometry.locations.size() >= 3
distance_from_end >= MINIMAL_RELATIVE_DISTANCE &&
distance_from_end <= MAXIMAL_RELATIVE_DISTANCE
? 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]))
leg_geometry.locations[leg_geometry.locations.size() - 1],
target_node.input_location))
: extractor::guidance::DirectionModifier::UTurn;
// This step has length zero, the only reason we need it is the target location
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()});
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()});
return steps;
}
+11 -2
View File
@@ -1,7 +1,8 @@
#ifndef ENGINE_GUIDANCE_POST_PROCESSING_HPP
#define ENGINE_GUIDANCE_POST_PROCESSING_HPP
#include "engine/internal_route_result.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include <vector>
@@ -12,7 +13,15 @@ namespace engine
namespace guidance
{
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> path_data);
// passed as none-reference to modify in-place and move out again
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.
// If required, we can get both in sync again using this function.
// Move in LegGeometry for modification in place.
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps);
} // namespace guidance
} // namespace engine
+10
View File
@@ -5,6 +5,7 @@
#include "extractor/guidance/turn_instruction.hpp"
#include <cstdint>
#include <vector>
namespace osrm
{
@@ -20,6 +21,14 @@ 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;
@@ -28,6 +37,7 @@ struct StepManeuver
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
std::vector<IntermediateIntersection> intersections;
};
} // namespace guidance
} // namespace engine
+15 -10
View File
@@ -34,39 +34,44 @@ 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;
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;
}
bool IsValid(const util::Coordinate new_input_coordinates,
const datafacade::BaseDataFacade &facade) const;
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
constexpr std::size_t ENCODED_HINT_SIZE = 84;
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 92;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
#endif
-2
View File
@@ -29,8 +29,6 @@ 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
@@ -1,91 +0,0 @@
#ifndef OBJECT_ENCODER_HPP
#define OBJECT_ENCODER_HPP
#include <boost/assert.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
#include <cstdint>
#include <climits>
namespace osrm
{
namespace engine
{
namespace detail
{
static_assert(CHAR_BIT == 8u, "we assume a byte holds 8 bits");
static_assert(sizeof(char) == 1u, "we assume a char is one byte large");
using Base64FromBinary = boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, // sequence of chars
6, // get view of 6 bit
8 // from sequence of 8 bit
>>;
using BinaryFromBase64 = boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
8, // get a view of 8 bit
6 // from a sequence of 6 bit
>;
} // ns detail
template <typename T> std::string encodeBase64(const T &x)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
std::vector<unsigned char> bytes{reinterpret_cast<const char *>(&x),
reinterpret_cast<const char *>(&x) + sizeof(T)};
BOOST_ASSERT(!bytes.empty());
std::size_t bytes_to_pad{0};
while (bytes.size() % 3 != 0)
{
bytes_to_pad += 1;
bytes.push_back(0);
}
BOOST_ASSERT(bytes_to_pad == 0 || bytes_to_pad == 1 || bytes_to_pad == 2);
BOOST_ASSERT_MSG(0 == bytes.size() % 3, "base64 input data size is not a multiple of 3");
std::string encoded{detail::Base64FromBinary{bytes.data()},
detail::Base64FromBinary{bytes.data() + (bytes.size() - bytes_to_pad)}};
std::replace(begin(encoded), end(encoded), '+', '-');
std::replace(begin(encoded), end(encoded), '/', '_');
return encoded;
}
template <typename T> T decodeBase64(std::string encoded)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
std::replace(begin(encoded), end(encoded), '-', '+');
std::replace(begin(encoded), end(encoded), '_', '/');
T rv;
std::copy(detail::BinaryFromBase64{begin(encoded)},
detail::BinaryFromBase64{begin(encoded) + encoded.length()},
reinterpret_cast<char *>(&rv));
return rv;
}
} // ns engine
} // ns osrm
#endif /* OBJECT_ENCODER_HPP */
+16 -5
View File
@@ -56,6 +56,7 @@ 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)
@@ -65,8 +66,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)),
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
{
}
@@ -115,6 +116,11 @@ struct PhantomNode
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
}
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; }
@@ -125,7 +131,8 @@ struct PhantomNode
int forward_offset_,
int reverse_weight_,
int reverse_offset_,
const util::Coordinate foot_point)
const util::Coordinate location_,
const util::Coordinate input_location_)
{
forward_node_id = other.forward_edge_based_node_id;
reverse_node_id = other.reverse_edge_based_node_id;
@@ -143,7 +150,8 @@ struct PhantomNode
component.id = other.component.id;
component.is_tiny = other.component.is_tiny;
location = foot_point;
location = location_;
input_location = input_location_;
fwd_segment_position = other.fwd_segment_position;
forward_travel_mode = other.forward_travel_mode;
@@ -169,6 +177,7 @@ 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
@@ -177,7 +186,9 @@ struct PhantomNode
};
#ifndef _MSC_VER
static_assert(sizeof(PhantomNode) == 52, "PhantomNode has more padding then expected");
static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected");
#else
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
#endif
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
-1
View File
@@ -5,7 +5,6 @@
#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,8 +299,7 @@ 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)
@@ -322,14 +321,17 @@ 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,
INVALID_EXIT_NR});
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode});
}
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
@@ -337,12 +339,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// However the first segment duration needs to be adjusted to the fact that the
// 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 >=
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;
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
unpacked_path.front().duration_until_turn -= source_weight;
}
}
}
@@ -388,7 +386,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
// note that (x, t) is _not_ included but needs to be added later.
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
{
BOOST_ASSERT(i < id_vector.size());
@@ -397,20 +395,20 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
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,
INVALID_EXIT_NR});
: phantom_node_pair.target_phantom.forward_travel_mode});
}
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 >=
phantom_node_pair.source_phantom.forward_weight);
unpacked_path.front().duration_until_turn -=
phantom_node_pair.source_phantom.forward_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 >= source_weight);
unpacked_path.front().duration_until_turn -= source_weight;
}
// there is no equivalent to a node-based node in an edge-expanded graph.
@@ -237,14 +237,10 @@ class ShortestPathRouting final
}
}
static const constexpr bool UTURN_DEFAULT = false;
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<boost::optional<bool>> &uturn_indicators,
const boost::optional<bool> uturns,
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(
@@ -270,7 +266,7 @@ class ShortestPathRouting final
std::vector<NodeID> total_packed_path_to_reverse;
std::vector<std::size_t> packed_leg_to_reverse_begin;
const bool use_uturn_indicators = !uturn_indicators.empty();
const bool allow_u_turn_at_via = uturns ? *uturns : super::facade->GetUTurnsDefault();
std::size_t current_leg = 0;
// this implements a dynamic program that finds the shortest route through
@@ -286,12 +282,6 @@ class ShortestPathRouting final
const auto &source_phantom = phantom_node_pair.source_phantom;
const auto &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/speed_profile.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_node.hpp"
@@ -17,6 +17,7 @@
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "util/deallocating_vector.hpp"
#include "util/name_table.hpp"
#include <algorithm>
#include <cstdint>
@@ -51,7 +52,8 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
SpeedProfileProperties speed_profile);
ProfileProperties profile_properties,
const util::NameTable &name_table);
void Run(const std::string &original_edge_data_filename,
lua_State *lua_state,
@@ -104,7 +106,9 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &m_traffic_lights;
const CompressedEdgeContainer &m_compressed_edge_container;
SpeedProfileProperties speed_profile;
ProfileProperties profile_properties;
const util::NameTable &name_table;
void CompressGeometry();
unsigned RenumberEdges();
+6 -2
View File
@@ -40,6 +40,8 @@ namespace osrm
namespace extractor
{
struct ProfileProperties;
class Extractor
{
public:
@@ -49,13 +51,15 @@ class Extractor
private:
ExtractorConfig config;
void SetupScriptingEnvironment(lua_State *myLuaState, SpeedProfileProperties &speed_profile);
std::pair<std::size_t, std::size_t>
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
BuildEdgeExpandedGraph(lua_State* lua_state,
const ProfileProperties& profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<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,6 +71,7 @@ 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;
@@ -88,6 +89,7 @@ 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,7 +3,6 @@
#include "util/typedefs.hpp"
#include "extractor/speed_profile.hpp"
#include "util/node_based_graph.hpp"
#include <memory>
@@ -22,8 +21,6 @@ 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,
@@ -34,8 +31,6 @@ class GraphCompressor
void PrintStatistics(unsigned original_number_of_nodes,
unsigned original_number_of_edges,
const util::NodeBasedDynamicGraph &graph) const;
SpeedProfileProperties speed_profile;
};
}
}
+91 -9
View File
@@ -12,9 +12,11 @@
#include "extractor/guidance/classification_data.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <algorithm>
#include <map>
#include <cmath>
#include <cstdint>
#include <string>
namespace osrm
{
@@ -249,10 +251,11 @@ inline double angularDeviation(const double angle, const double from)
return std::min(360 - deviation, deviation);
}
inline double getAngularPenalty(const double angle, TurnInstruction instruction)
inline double getAngularPenalty(const double angle, DirectionModifier modifier)
{
// these are not aligned with getTurnDirection but represent an ideal center
const double center[] = {0, 45, 90, 135, 180, 225, 270, 315};
return angularDeviation(center[static_cast<int>(instruction.direction_modifier)], angle);
return angularDeviation(center[static_cast<int>(modifier)], angle);
}
inline double getTurnConfidence(const double angle, TurnInstruction instruction)
@@ -262,8 +265,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, 35, 10, 35, 50, 45};
const double difference = getAngularPenalty(angle, instruction);
const double deviations[] = {0, 45, 50, 30, 20, 30, 50, 45};
const double difference = getAngularPenalty(angle, instruction.direction_modifier);
const double max_deviation = deviations[static_cast<int>(instruction.direction_modifier)];
return 1.0 - (difference / max_deviation) * (difference / max_deviation);
}
@@ -281,7 +284,7 @@ inline DirectionModifier getTurnDirection(const double angle)
return DirectionModifier::Right;
if (angle >= 140 && angle < 170)
return DirectionModifier::SlightRight;
if (angle >= 170 && angle <= 190)
if (angle >= 165 && angle <= 195)
return DirectionModifier::Straight;
if (angle > 190 && angle <= 220)
return DirectionModifier::SlightLeft;
@@ -295,10 +298,14 @@ 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];
}
@@ -315,6 +322,81 @@ 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
+88 -93
View File
@@ -6,11 +6,14 @@
#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
@@ -20,42 +23,59 @@ namespace extractor
namespace guidance
{
struct TurnCandidate
// What is exposed to the outside
struct TurnOperation final
{
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?
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
std::string toString() const
{
std::string result = "[turn] ";
result += std::to_string(eid);
result += " valid: ";
result += std::to_string(valid);
std::string result = "[connection] ";
result += std::to_string(turn.eid);
result += " allows entry: ";
result += std::to_string(entry_allowed);
result += " angle: ";
result += std::to_string(angle);
result += std::to_string(turn.angle);
result += " instruction: ";
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);
result += std::to_string(static_cast<std::int32_t>(turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(turn.instruction.direction_modifier));
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 CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table);
// the entry into the turn analysis
std::vector<TurnCandidate> getTurns(const NodeID from_node, const EdgeID via_eid) const;
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -63,12 +83,14 @@ 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<TurnCandidate> getTurnCandidates(const NodeID from_node,
std::vector<ConnectedRoad> getConnectedRoads(const NodeID from_node,
const EdgeID via_eid) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
@@ -82,10 +104,7 @@ class TurnAnalysis
//
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
// 160
std::vector<TurnCandidate>
mergeSegregatedRoads(const NodeID from_node,
const EdgeID via_eid,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> mergeSegregatedRoads(std::vector<ConnectedRoad> intersection) const;
// TODO distinguish roundabouts and rotaries
// TODO handle bike/walk cases that allow crossing a roundabout!
@@ -93,110 +112,86 @@ 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<TurnCandidate> handleRoundabouts(const NodeID from,
const EdgeID via_edge,
std::vector<ConnectedRoad> handleRoundabouts(const EdgeID via_edge,
const bool on_roundabout,
const bool can_enter_roundabout,
const bool can_exit_roundabout,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> intersection) const;
// Indicates a Junction containing a motoryway
bool isMotorwayJunction(const NodeID from,
const EdgeID via_edge,
const std::vector<TurnCandidate> &turn_candidates) const;
bool isMotorwayJunction(const EdgeID via_edge,
const std::vector<ConnectedRoad> &intersection) const;
// Decide whether a turn is a turn or a ramp access
TurnType findBasicTurnType(const EdgeID via_edge, const TurnCandidate &candidate) const;
TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
// Get the Instruction for an obvious turn
// Instruction will be a silent instruction
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
const EdgeID via_edge,
const TurnCandidate &candidate) const;
const ConnectedRoad &candidate) const;
// Helper Function that decides between NoTurn or NewName
TurnInstruction
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const TurnCandidate &candidate) const;
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const;
// Basic Turn Handling
// Dead end.
std::vector<TurnCandidate> handleOneWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleOneWayTurn(std::vector<ConnectedRoad> intersection) const;
// Mode Changes, new names...
std::vector<TurnCandidate> handleTwoWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleTwoWayTurn(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
// Forks, T intersections and similar
std::vector<TurnCandidate> handleThreeWayTurn(const NodeID from,
const EdgeID via_edge,
std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleThreeWayTurn(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;
// Handling of turns larger then degree three
std::vector<ConnectedRoad> handleComplexTurn(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
// Any Junction containing motorways
std::vector<TurnCandidate> handleMotorwayJunction(
const NodeID from, const EdgeID via_edge, std::vector<TurnCandidate> turn_candidates) const;
std::vector<ConnectedRoad> handleMotorwayJunction(
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> handleFromMotorway(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;
std::vector<ConnectedRoad> handleMotorwayRamp(const EdgeID via_edge,
std::vector<ConnectedRoad> intersection) const;
// Utility function, setting basic turn types. Prepares for normal turn handling.
std::vector<TurnCandidate> setTurnTypes(const NodeID from,
std::vector<ConnectedRoad> setTurnTypes(const NodeID from,
const EdgeID via_edge,
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;
std::vector<ConnectedRoad> intersection) const;
// Assignment of specific turn types
void assignFork(const EdgeID via_edge, TurnCandidate &left, TurnCandidate &right) const;
void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
void assignFork(const EdgeID via_edge,
TurnCandidate &left,
TurnCandidate &center,
TurnCandidate &right) const;
ConnectedRoad &left,
ConnectedRoad &center,
ConnectedRoad &right) const;
//Type specific fallbacks
std::vector<TurnCandidate>
fallbackTurnAssignmentMotorway(std::vector<TurnCandidate> turn_candidates) 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;
}; // class TurnAnalysis
@@ -42,8 +42,16 @@ enum TurnType // at the moment we can support 32 turn types, without increasing
NewName, // no turn, but name changes
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
@@ -0,0 +1,48 @@
#ifndef PROFILE_PROPERTIES_HPP
#define PROFILE_PROPERTIES_HPP
#include <boost/numeric/conversion/cast.hpp>
namespace osrm
{
namespace extractor
{
struct ProfileProperties
{
ProfileProperties()
: traffic_signal_penalty(0), u_turn_penalty(0), allow_u_turn_at_via(false), use_turn_restrictions(false)
{
}
double GetUturnPenalty() const
{
return u_turn_penalty / 10.;
}
void SetUturnPenalty(const double u_turn_penalty_)
{
u_turn_penalty = boost::numeric_cast<int>(u_turn_penalty_ * 10.);
}
double GetTrafficSignalPenalty() const
{
return traffic_signal_penalty / 10.;
}
void SetTrafficSignalPenalty(const double traffic_signal_penalty_)
{
traffic_signal_penalty = boost::numeric_cast<int>(traffic_signal_penalty_ * 10.);
}
//! penalty to cross a traffic light in deci-seconds
int traffic_signal_penalty;
//! penalty to do a uturn in deci-seconds
int u_turn_penalty;
bool allow_u_turn_at_via;
bool use_turn_restrictions;
};
}
}
#endif
+3 -2
View File
@@ -19,6 +19,8 @@ namespace osrm
namespace extractor
{
class ProfileProperties;
/**
* Parses the relations that represents turn restrictions.
*
@@ -40,11 +42,10 @@ namespace extractor
class RestrictionParser
{
public:
RestrictionParser(lua_State *lua_state);
RestrictionParser(lua_State *lua_state, const ProfileProperties& properties);
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;
+15 -3
View File
@@ -1,6 +1,11 @@
#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>
@@ -23,18 +28,25 @@ 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;
lua_State *GetLuaState();
Context &GetContex();
private:
void InitLuaState(lua_State *lua_state);
void InitContext(Context &context);
std::mutex init_mutex;
std::string file_name;
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
tbb::enumerable_thread_specific<std::unique_ptr<Context>> script_contexts;
};
}
}
-23
View File
@@ -1,23 +0,0 @@
#ifndef SPEED_PROFILE_PROPERTIES_HPP
#define SPEED_PROFILE_PROPERTIES_HPP
namespace osrm
{
namespace extractor
{
struct SpeedProfileProperties
{
SpeedProfileProperties()
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
{
}
int traffic_signal_penalty;
int u_turn_penalty;
bool has_turn_penalty_function;
};
}
}
#endif
+38
View File
@@ -0,0 +1,38 @@
/*
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GLOBAL_STORAGE_CONFIG_HPP
#define GLOBAL_STORAGE_CONFIG_HPP
#include "storage/storage_config.hpp"
namespace osrm
{
using storage::StorageConfig;
}
#endif
@@ -27,7 +27,7 @@ struct RouteParametersGrammar : public BaseParametersGrammar
using AlternativeT = bool;
using GeometriesT = engine::api::RouteParameters::GeometriesType;
using OverviewT = engine::api::RouteParameters::OverviewType;
using UturnsT = std::vector<boost::optional<bool>>;
using UturnsT = 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=") >> -qi::bool_ % ";";
uturns_rule = qi::lit("uturns=default") | (qi::lit("uturns=") >> qi::bool_)[set_uturns];
route_rule = steps_rule[set_steps] | alternatives_rule[set_alternatives] | geometries_rule |
overview_rule | uturns_rule[set_uturns];
overview_rule | uturns_rule;
root_rule =
query_rule >> -qi::lit(".json") >> -(qi::lit("?") >> (route_rule | base_rule) % '&');
+3
View File
@@ -52,6 +52,9 @@ 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,6 +41,7 @@ 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(const DataPaths &data_paths);
Storage(StorageConfig config);
int Run();
private:
DataPaths paths;
StorageConfig config;
};
}
}
+32
View File
@@ -0,0 +1,32 @@
#ifndef STORAGE_CONFIG_HPP
#define STORAGE_CONFIG_HPP
#include <boost/filesystem/path.hpp>
namespace osrm
{
namespace storage
{
struct StorageConfig
{
StorageConfig() = default;
StorageConfig(const boost::filesystem::path &base);
bool IsValid() const;
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
boost::filesystem::path hsgr_data_path;
boost::filesystem::path nodes_data_path;
boost::filesystem::path edges_data_path;
boost::filesystem::path core_data_path;
boost::filesystem::path geometries_path;
boost::filesystem::path timestamp_path;
boost::filesystem::path datasource_names_path;
boost::filesystem::path datasource_indexes_path;
boost::filesystem::path names_data_path;
boost::filesystem::path properties_path;
};
}
}
#endif
+25 -5
View File
@@ -3,20 +3,34 @@
#include "util/coordinate.hpp"
#include <boost/math/constants/constants.hpp>
#include <utility>
namespace osrm
{
namespace util
{
namespace coordinate_calculation
{
const constexpr long double RAD = 0.017453292519943295769236907684886;
const constexpr long double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// 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 coordinate_calculation
namespace detail
{
// earth circumference devided by 2
const constexpr double MAXEXTENT = EARTH_RADIUS_WGS84 * boost::math::constants::pi<double>();
// ^ math functions are not constexpr since they have side-effects (setting errno) :(
const double MAX_LATITUDE = RAD_TO_DEGREE * (2.0 * std::atan(std::exp(180.0 * DEGREE_TO_RAD)) - boost::math::constants::half_pi<double>());
const constexpr double MAX_LONGITUDE = 180.0;
}
//! Projects both coordinates and takes the euclidean distance of the projected points
// Does not return meters!
@@ -50,9 +64,6 @@ 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)
@@ -64,8 +75,17 @@ 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
+11 -2
View File
@@ -18,10 +18,19 @@ namespace osrm
namespace util
{
template <typename T> void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; }
struct LuaState
{
LuaState() : handle{::luaL_newstate(), &::lua_close} { luaL_openlibs(*this); }
operator lua_State *() { return handle.get(); }
operator lua_State const *() const { return handle.get(); }
using handle_type = std::unique_ptr<lua_State, decltype(&::lua_close)>;
handle_type handle;
};
// Check if the lua function <name> is defined
inline bool lua_function_exists(lua_State *lua_state, const char *name)
inline bool luaFunctionExists(lua_State *lua_state, const char *name)
{
luabind::object globals_table = luabind::globals(lua_state);
luabind::object lua_function = globals_table[name];
+31
View File
@@ -0,0 +1,31 @@
#ifndef OSRM_UTIL_NAME_TABLE_HPP
#define OSRM_UTIL_NAME_TABLE_HPP
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/range_table.hpp"
#include <string>
namespace osrm
{
namespace util
{
// While this could, theoretically, hold any names in the fitting format,
// the NameTable allows access to a part of the Datafacade to allow
// processing based on name indices.
class NameTable
{
private:
// FIXME should this use shared memory
RangeTable<16, false> m_name_table;
ShM<char, false>::vector m_names_char_list;
public:
NameTable(const std::string &filename);
std::string GetNameForID(const unsigned name_id) const;
};
} // namespace util
} // namespace osrm
#endif // OSRM_UTIL_NAME_TABLE_HPP
-251
View File
@@ -1,251 +0,0 @@
#ifndef ROUTED_OPTIONS_HPP
#define ROUTED_OPTIONS_HPP
#include "util/version.hpp"
#include "util/exception.hpp"
#include "util/simple_logger.hpp"
#include <boost/any.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
#include <unordered_map>
#include <fstream>
#include <string>
namespace osrm
{
namespace util
{
const static unsigned INIT_OK_START_ENGINE = 0;
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
const static unsigned INIT_FAILED = -1;
inline void
populate_base_path(std::unordered_map<std::string, boost::filesystem::path> &server_paths)
{
// populate the server_path object
auto path_iterator = server_paths.find("base");
// if a base path has been set, we populate it.
if (path_iterator != server_paths.end())
{
const std::string base_string = path_iterator->second.string();
SimpleLogger().Write() << "populating base path: " << base_string;
server_paths["hsgrdata"] = base_string + ".hsgr";
BOOST_ASSERT(server_paths.find("hsgrdata") != server_paths.end());
server_paths["nodesdata"] = base_string + ".nodes";
BOOST_ASSERT(server_paths.find("nodesdata") != server_paths.end());
server_paths["coredata"] = base_string + ".core";
BOOST_ASSERT(server_paths.find("coredata") != server_paths.end());
server_paths["edgesdata"] = base_string + ".edges";
BOOST_ASSERT(server_paths.find("edgesdata") != server_paths.end());
server_paths["geometries"] = base_string + ".geometry";
BOOST_ASSERT(server_paths.find("geometries") != server_paths.end());
server_paths["ramindex"] = base_string + ".ramIndex";
BOOST_ASSERT(server_paths.find("ramindex") != server_paths.end());
server_paths["fileindex"] = base_string + ".fileIndex";
BOOST_ASSERT(server_paths.find("fileindex") != server_paths.end());
server_paths["namesdata"] = base_string + ".names";
BOOST_ASSERT(server_paths.find("namesdata") != server_paths.end());
server_paths["timestamp"] = base_string + ".timestamp";
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
server_paths["datasource_indexes"] = base_string + ".datasource_indexes";
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
server_paths["datasource_names"] = base_string + ".datasource_names";
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
}
// check if files are give and whether they exist at all
path_iterator = server_paths.find("hsgrdata");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".hsgr not found");
}
path_iterator = server_paths.find("nodesdata");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".nodes not found");
}
path_iterator = server_paths.find("edgesdata");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".edges not found");
}
path_iterator = server_paths.find("geometries");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".geometry not found");
}
path_iterator = server_paths.find("ramindex");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".ramIndex not found");
}
path_iterator = server_paths.find("fileindex");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".fileIndex not found");
}
path_iterator = server_paths.find("namesdata");
if (path_iterator == server_paths.end() ||
!boost::filesystem::is_regular_file(path_iterator->second))
{
throw exception(".namesIndex not found");
}
SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"];
SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"];
SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"];
SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"];
SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"];
SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"];
SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"];
}
// generate boost::program_options object for the routing part
inline unsigned
GenerateServerProgramOptions(const int argc,
const char *argv[],
std::unordered_map<std::string, boost::filesystem::path> &paths,
std::string &ip_address,
int &ip_port,
int &requested_num_threads,
bool &use_shared_memory,
bool &trial,
int &max_locations_trip,
int &max_locations_viaroute,
int &max_locations_distance_table,
int &max_locations_map_matching)
{
using boost::program_options::value;
using boost::filesystem::path;
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options() //
("version,v", "Show version")("help,h", "Show this help message") //
("config,c", value<boost::filesystem::path>(&paths["config"])->default_value("server.ini"),
"Path to a configuration file") //
("trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
// declare a group of options that will be allowed on command line
boost::program_options::options_description config_options("Configuration");
config_options.add_options() //
("hsgrdata", value<boost::filesystem::path>(&paths["hsgrdata"]), ".hsgr file") //
("nodesdata", value<boost::filesystem::path>(&paths["nodesdata"]), ".nodes file") //
("edgesdata", value<boost::filesystem::path>(&paths["edgesdata"]), ".edges file") //
("geometry", value<boost::filesystem::path>(&paths["geometries"]), ".geometry file") //
("ramindex", value<boost::filesystem::path>(&paths["ramindex"]), ".ramIndex file") //
("fileindex", value<boost::filesystem::path>(&paths["fileindex"]),
"File index file") //
("namesdata", value<boost::filesystem::path>(&paths["namesdata"]),
".names file") //
("timestamp", value<boost::filesystem::path>(&paths["timestamp"]),
".timestamp file") //
("ip,i", value<std::string>(&ip_address)->default_value("0.0.0.0"),
"IP address") //
("port,p", value<int>(&ip_port)->default_value(5000),
"TCP/IP port") //
("threads,t", value<int>(&requested_num_threads)->default_value(8),
"Number of threads to use") //
("shared-memory,s",
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false),
"Load data from shared memory") //
("max-viaroute-size", value<int>(&max_locations_viaroute)->default_value(500),
"Max. locations supported in viaroute query") //
("max-trip-size", value<int>(&max_locations_trip)->default_value(100),
"Max. locations supported in trip query") //
("max-table-size", value<int>(&max_locations_distance_table)->default_value(100),
"Max. locations supported in distance table query") //
("max-matching-size", value<int>(&max_locations_map_matching)->default_value(100),
"Max. locations supported in map matching query");
// hidden options, will be allowed on command line, but will not be shown to the user
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()("base,b", value<boost::filesystem::path>(&paths["base"]),
"base path to .osrm file");
// positional option
boost::program_options::positional_options_description positional_options;
positional_options.add("base", 1);
// combine above options for parsing
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
boost::program_options::options_description visible_options(
boost::filesystem::basename(argv[0]) + " <base.osrm> [<options>]");
visible_options.add(generic_options).add(config_options);
// parse command line options
boost::program_options::variables_map option_variables;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
.options(cmdline_options)
.positional(positional_options)
.run(),
option_variables);
if (option_variables.count("version"))
{
SimpleLogger().Write() << OSRM_VERSION;
return INIT_OK_DO_NOT_START_ENGINE;
}
if (option_variables.count("help"))
{
SimpleLogger().Write() << visible_options;
return INIT_OK_DO_NOT_START_ENGINE;
}
boost::program_options::notify(option_variables);
if (1 > requested_num_threads)
{
throw exception("Number of threads must be a positive number");
}
if (2 > max_locations_distance_table)
{
throw exception("Max location for distance table must be at least two");
}
if (max_locations_map_matching > 0 && 2 > max_locations_map_matching)
{
throw exception("Max location for map matching must be at least two");
}
if (!use_shared_memory && option_variables.count("base"))
{
return INIT_OK_START_ENGINE;
}
else if (use_shared_memory && !option_variables.count("base"))
{
return INIT_OK_START_ENGINE;
}
else if (use_shared_memory && option_variables.count("base"))
{
SimpleLogger().Write(logWARNING) << "Shared memory settings conflict with path settings.";
}
SimpleLogger().Write() << visible_options;
return INIT_OK_DO_NOT_START_ENGINE;
}
}
}
#endif // ROUTED_OPTIONS_HPP
-87
View File
@@ -1,87 +0,0 @@
#ifndef UTIL_TILES_HPP
#define UTIL_TILES_HPP
#include "util/coordinate.hpp"
#include <boost/assert.hpp>
#include <cmath>
#include <tuple>
// This is a port of the tilebelt algorithm https://github.com/mapbox/tilebelt
namespace osrm
{
namespace util
{
namespace tiles
{
struct Tile
{
unsigned x;
unsigned y;
unsigned z;
};
namespace detail
{
// optimized for 32bit integers
static constexpr unsigned MAX_ZOOM = 32;
// Returns 1-indexed 1..32 of MSB if value > 0 or 0 if value == 0
inline unsigned getMSBPosition(std::uint32_t value)
{
if (value == 0)
return 0;
std::uint8_t pos = 1;
while (value >>= 1)
pos++;
return pos;
}
inline unsigned getBBMaxZoom(const Tile top_left, const Tile bottom_left)
{
auto x_xor = top_left.x ^ bottom_left.x;
auto y_xor = top_left.y ^ bottom_left.y;
auto lon_msb = detail::getMSBPosition(x_xor);
auto lat_msb = detail::getMSBPosition(y_xor);
return MAX_ZOOM - std::max(lon_msb, lat_msb);
}
}
inline Tile pointToTile(const FloatLongitude lon, const FloatLatitude lat)
{
auto sin_lat = std::sin(static_cast<double>(lat) * M_PI / 180.);
auto p2z = std::pow(2, detail::MAX_ZOOM);
unsigned x = p2z * (static_cast<double>(lon) / 360. + 0.5);
unsigned y = p2z * (0.5 - 0.25 * std::log((1 + sin_lat) / (1 - sin_lat)) / M_PI);
return Tile{x, y, detail::MAX_ZOOM};
}
inline Tile getBBMaxZoomTile(const FloatLongitude min_lon,
const FloatLatitude min_lat,
const FloatLongitude max_lon,
const FloatLatitude max_lat)
{
const auto top_left = pointToTile(min_lon, min_lat);
const auto bottom_left = pointToTile(max_lon, max_lat);
BOOST_ASSERT(top_left.z == detail::MAX_ZOOM);
BOOST_ASSERT(bottom_left.z == detail::MAX_ZOOM);
const auto max_zoom = detail::getBBMaxZoom(top_left, bottom_left);
if (max_zoom == 0)
{
return Tile{0, 0, 0};
}
auto x = top_left.x >> (detail::MAX_ZOOM - max_zoom);
auto y = top_left.y >> (detail::MAX_ZOOM - max_zoom);
return Tile{x, y, max_zoom};
}
}
}
}
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef UTIL_VIEWPORT_HPP
#define UTIL_VIEWPORT_HPP
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include <boost/assert.hpp>
#include <cmath>
#include <tuple>
// Port of https://github.com/mapbox/geo-viewport
namespace osrm
{
namespace util
{
namespace viewport
{
namespace detail
{
static constexpr unsigned MAX_ZOOM = 18;
static constexpr unsigned MIN_ZOOM = 1;
// this is an upper bound to current display sizes
static constexpr double VIEWPORT_WIDTH = 8 * coordinate_calculation::mercator::TILE_SIZE;
static constexpr double VIEWPORT_HEIGHT = 5 * coordinate_calculation::mercator::TILE_SIZE;
static double INV_LOG_2 = 1. / std::log(2);
}
unsigned getFittedZoom(util::Coordinate south_west, util::Coordinate north_east)
{
const auto min_x = coordinate_calculation::mercator::degreeToPixel(toFloating(south_west.lon), detail::MAX_ZOOM);
const auto max_y = coordinate_calculation::mercator::degreeToPixel(toFloating(south_west.lat), detail::MAX_ZOOM);
const auto max_x = coordinate_calculation::mercator::degreeToPixel(toFloating(north_east.lon), detail::MAX_ZOOM);
const auto min_y = coordinate_calculation::mercator::degreeToPixel(toFloating(north_east.lat), detail::MAX_ZOOM);
const double width_ratio = (max_x - min_x) / detail::VIEWPORT_WIDTH;
const double height_ratio = (max_y - min_y) / detail::VIEWPORT_HEIGHT;
const auto zoom = detail::MAX_ZOOM - std::max(std::log(width_ratio), std::log(height_ratio)) * detail::INV_LOG_2;
return std::max<unsigned>(detail::MIN_ZOOM, zoom);
}
}
}
}
#endif
+4 -3
View File
@@ -91,9 +91,10 @@ surface_speeds = {
}
-- these need to be global because they are accesed externaly
traffic_signal_penalty = 2
use_turn_restrictions = false
u_turn_penalty = 20
properties.traffic_signal_penalty = 2
properties.use_turn_restrictions = false
properties.u_turn_penalty = 20
properties.allow_u_turn_at_via = true
local obey_oneway = true
local ignore_areas = true
+9 -9
View File
@@ -128,20 +128,20 @@ maxspeed_table = {
["uk:motorway"] = (70*1609)/1000
}
-- these need to be global because they are accesed externaly
u_turn_penalty = 20
traffic_signal_penalty = 2
use_turn_restrictions = true
-- set profile properties
properties.u_turn_penalty = 20
properties.traffic_signal_penalty = 2
properties.use_turn_restrictions = true
side_road_speed_multiplier = 0.8
local side_road_speed_multiplier = 0.8
local turn_penalty = 10
local turn_penalty = 10
-- Note: this biases right-side driving. Should be
-- 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
+5 -3
View File
@@ -64,9 +64,11 @@ leisure_speeds = {
["track"] = walking_speed
}
traffic_signal_penalty = 2
u_turn_penalty = 2
use_turn_restrictions = false
properties.traffic_signal_penalty = 2
properties.u_turn_penalty = 2
properties.use_turn_restrictions = false
properties.allow_u_turn_at_via = true
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)
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
local slope = math.abs(sourceData.datum - targetData.datum) / distance
print (" slope: " .. slope)
print (" was speed: " .. weight.speed)
io.write(" slope: " .. slope .. "\n")
io.write(" was speed: " .. weight.speed .. "\n")
weight.speed = weight.speed * (1 - (slope * 5))
print (" new speed: " .. weight.speed)
io.write(" new speed: " .. weight.speed .. "\n")
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)
print ("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum)
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
local slope = math.abs(sourceData.datum - targetData.datum) / distance
print (" slope: " .. slope)
print (" was speed: " .. weight.speed)
io.write(" slope: " .. slope .. "\n")
io.write(" was speed: " .. weight.speed .. "\n")
weight.speed = weight.speed * (1 - (slope * 5))
print (" new speed: " .. weight.speed)
io.write(" new speed: " .. weight.speed .. "\n")
end
end
+4 -7
View File
@@ -16,13 +16,10 @@ speed_profile = {
-- these settings are read directly by osrm
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
properties.allow_u_turn_at_via = false
properties.use_turn_restrictions = true
properties.traffic_signal_penalty = 7 -- seconds
properties.u_turn_penalty = 20
function limit_speed(speed, limits)
-- don't use ipairs(), since it stops at the first nil value
+28 -21
View File
@@ -173,6 +173,10 @@ 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;
@@ -264,7 +268,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.
std::vector<uint8_t> m_geometry_datasource(m_geometry_list.size(), 0);
m_geometry_datasource.resize(m_geometry_list.size(), 0);
// Now, we iterate over all the segments stored in the StaticRTree, updating
// the packed geometry weights in the `.geometries` file (note: we do not
@@ -402,33 +406,36 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
number_of_compressed_geometries *
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)
{
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;
}
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;
}
}
+11 -5
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",
"merge", "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",
"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"};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
// Check whether to include a modifier in the result of the API
@@ -149,6 +149,12 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
step_maneuver.values["bearing_after"] = maneuver.bearing_after;
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;
}
+10 -8
View File
@@ -27,28 +27,30 @@ 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)) * 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;
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;
}
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)) * util::RAD;
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * util::RAD;
const float float_lon1 = static_cast<double>(toFloating(other.lon)) * DEGREE_TO_RAD;
const float float_lat1 = static_cast<double>(toFloating(other.lat)) * DEGREE_TO_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) * util::EARTH_RADIUS;
const float dist1 = std::hypot(x_value_1, y_value_1) * 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) * util::EARTH_RADIUS;
const float dist2 = std::hypot(x_value_2, y_value_2) * EARTH_RADIUS;
// return the minimum
return static_cast<int>(std::min(dist1, dist2));
+5 -3
View File
@@ -18,7 +18,6 @@
#include "storage/shared_barriers.hpp"
#include "util/make_unique.hpp"
#include "util/routed_options.hpp"
#include "util/simple_logger.hpp"
#include <boost/assert.hpp>
@@ -136,8 +135,11 @@ Engine::Engine(EngineConfig &config)
}
else
{
util::populate_base_path(config.server_paths);
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.server_paths);
if (!config.storage_config.IsValid())
{
throw util::exception("Invalid file paths given!");
}
query_data_facade = util::make_unique<datafacade::InternalDataFacade>(config.storage_config);
}
// Register plugins
+27
View File
@@ -0,0 +1,27 @@
#include "engine/engine_config.hpp"
namespace osrm
{
namespace engine
{
bool EngineConfig::IsValid() const
{
const bool all_path_are_empty =
storage_config.ram_index_path.empty() && storage_config.file_index_path.empty() &&
storage_config.hsgr_data_path.empty() && storage_config.nodes_data_path.empty() &&
storage_config.edges_data_path.empty() && storage_config.core_data_path.empty() &&
storage_config.geometries_path.empty() && storage_config.timestamp_path.empty() &&
storage_config.datasource_names_path.empty() &&
storage_config.datasource_indexes_path.empty() && storage_config.names_data_path.empty();
const bool limits_valid =
(max_locations_distance_table == -1 || max_locations_distance_table > 2) &&
(max_locations_map_matching == -1 || max_locations_map_matching > 2) &&
(max_locations_trip == -1 || max_locations_trip > 2) &&
(max_locations_viaroute == -1 || max_locations_viaroute > 2);
return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid;
}
}
}
+10 -13
View File
@@ -3,7 +3,7 @@
#include "engine/guidance/leg_geometry.hpp"
#include "engine/douglas_peucker.hpp"
#include "util/tiles.hpp"
#include "util/viewport.hpp"
#include <vector>
#include <tuple>
@@ -23,25 +23,22 @@ namespace
unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometries)
{
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()};
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()}};
for (const auto &leg_geometry : leg_geometries)
{
for (const auto coord : leg_geometry.locations)
{
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);
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);
}
}
return util::tiles::getBBMaxZoomTile(toFloating(min_lon), toFloating(min_lat),
toFloating(max_lon), toFloating(max_lat))
.z;
return util::viewport::getFittedZoom(south_west, north_east);
}
std::vector<util::Coordinate> simplifyGeometry(const std::vector<LegGeometry> &leg_geometries,
@@ -70,7 +67,7 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
{
if (use_simplification)
{
const auto zoom_level = calculateOverviewZoomLevel(leg_geometries);
const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries));
return simplifyGeometry(leg_geometries, zoom_level);
}
BOOST_ASSERT(!use_simplification);
+46 -4
View File
@@ -12,15 +12,49 @@ 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 unsigned exit)
const std::size_t segment_index)
{
auto turn_index = leg_geometry.BackIndex(segment_index);
BOOST_ASSERT(turn_index > 0);
BOOST_ASSERT(turn_index < leg_geometry.locations.size());
BOOST_ASSERT(turn_index + 1 < leg_geometry.locations.size());
// TODO chose a bigger look-a-head to smooth complex geometry
const auto pre_turn_coordinate = leg_geometry.locations[turn_index - 1];
@@ -32,7 +66,15 @@ StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instr
const double post_turn_bearing =
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
return StepManeuver{turn_coordinate, pre_turn_bearing, post_turn_bearing, instruction, waypoint_type, exit};
return StepManeuver{
std::move(turn_coordinate),
pre_turn_bearing,
post_turn_bearing,
std::move(instruction),
WaypointType::None,
INVALID_EXIT_NR,
{} // no intermediate intersections
};
}
} // ns detail
} // ns engine
+258 -155
View File
@@ -4,8 +4,11 @@
#include "engine/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <iostream>
#include <vector>
#include <cstddef>
#include <utility>
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
using TurnType = osrm::extractor::guidance::TurnType;
@@ -20,196 +23,296 @@ namespace guidance
namespace detail
{
bool canMergeTrivially(const PathData &destination, const PathData &source)
bool canMergeTrivially(const RouteStep &destination, const RouteStep &source)
{
return destination.exit == 0 && destination.name_id == source.name_id &&
destination.travel_mode == source.travel_mode && isSilent(source.turn_instruction);
return destination.maneuver.exit == 0 && destination.name_id == source.name_id &&
isSilent(source.maneuver.instruction);
}
PathData forwardInto(PathData destination, const PathData &source)
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
{
// Merge a turn into a silent turn
// Overwrites turn instruction and increases exit NR
destination.duration_until_turn += source.duration_until_turn;
destination.exit = source.exit;
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);
return destination;
}
PathData accumulateInto(PathData destination, const PathData &source)
void fixFinalRoundabout(std::vector<RouteStep> &steps)
{
// 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;
}
PathData mergeInto(PathData destination, const PathData &source)
{
if (source.turn_instruction == TurnInstruction::NO_TURN())
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
--propagation_index)
{
BOOST_ASSERT(canMergeTrivially(destination, source));
return detail::forwardInto(destination, source);
}
if (source.turn_instruction.type == TurnType::Suppressed)
{
return detail::forwardInto(destination, source);
}
if (source.turn_instruction.type == TurnType::StayOnRoundabout)
{
return detail::forwardInto(destination, source);
}
if (entersRoundabout(source.turn_instruction))
{
return detail::forwardInto(destination, source);
}
return destination;
}
} // namespace detail
void print(const std::vector<std::vector<PathData>> &leg_data)
{
std::cout << "Path\n";
int legnr = 0;
for (const auto &leg : leg_data)
{
std::cout << "\tLeg: " << ++legnr << "\n";
int segment = 0;
for (const auto &data : leg)
auto &propagation_step = steps[propagation_index];
if (entersRoundabout(propagation_step.maneuver.instruction))
{
const auto type = static_cast<int>(data.turn_instruction.type);
const auto modifier = static_cast<int>(data.turn_instruction.direction_modifier);
std::cout << "\t\t[" << ++segment << "]: " << type << " " << modifier
<< " exit: " << data.exit << "\n";
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
}
}
std::cout << std::endl;
}
std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
bool setUpRoundabout(RouteStep &step)
{
if (leg_data.empty())
return leg_data;
// 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)
{
step.maneuver.exit = 1;
// prevent futher special case handling of these two.
if (instruction.type == TurnType::EnterRotaryAtExit)
step.maneuver.instruction = TurnType::EnterRotary;
else
step.maneuver.instruction = TurnType::EnterRoundabout;
}
#define PRINT_DEBUG 0
unsigned carry_exit = 0;
#if PRINT_DEBUG
if (leavesRoundabout(instruction))
{
step.maneuver.exit = 1; // count the otherwise missing exit
if (instruction.type == TurnType::EnterRotaryAtExit)
step.maneuver.instruction = TurnType::EnterRotary;
else
step.maneuver.instruction = TurnType::EnterRoundabout;
return false;
}
else
{
return true;
}
}
void closeOffRoundabout(const bool on_roundabout,
std::vector<RouteStep> &steps,
const std::size_t step_index)
{
auto &step = steps[step_index];
step.maneuver.exit += 1;
if (!on_roundabout)
{
// We reached a special case that requires the addition of a special route step in
// the beginning.
// We started in a roundabout, so to announce the exit, we move use the exit
// instruction and
// move it right to the beginning to make sure to immediately announce the exit.
BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) ||
steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout);
steps[0].geometry_end = 1;
steps[1] = detail::forwardInto(steps[1], steps[0]);
steps[0].duration = 0;
steps[0].distance = 0;
steps[1].maneuver.instruction.type = step.maneuver.instruction.type == TurnType::ExitRotary
? TurnType::EnterRotary
: TurnType::EnterRoundabout;
}
// Normal exit from the roundabout, or exit from a previously fixed roundabout.
// Propagate the index back to the entering
// location and
// prepare the current silent set of instructions for removal.
if (step_index > 1)
{
// The very first route-step is head, so we cannot iterate past that one
for (std::size_t propagation_index = step_index - 1; propagation_index > 0;
--propagation_index)
{
auto &propagation_step = steps[propagation_index];
propagation_step = detail::forwardInto(propagation_step, steps[propagation_index + 1]);
if (entersRoundabout(propagation_step.maneuver.instruction))
{
// TODO at this point, we can remember the additional name for a rotary
// This requires some initial thought on the data format, though
propagation_step.maneuver.exit = step.maneuver.exit;
propagation_step.geometry_end = step.geometry_end;
propagation_step.name = step.name;
propagation_step.name_id = step.name_id;
break;
}
else
{
BOOST_ASSERT(propagation_step.maneuver.instruction.type =
TurnType::StayOnRoundabout);
propagation_step.maneuver.instruction =
TurnInstruction::NO_TURN(); // mark intermediate instructions invalid
}
}
// remove exit
step.maneuver.instruction = TurnInstruction::NO_TURN();
}
}
} // namespace detail
void print(const std::vector<RouteStep> &steps)
{
std::cout << "Path\n";
int segment = 0;
for (const auto &step : steps)
{
const auto type = static_cast<int>(step.maneuver.instruction.type);
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
<< " Duration: " << step.duration << " Distance: " << step.distance
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
<< " exit: " << step.maneuver.exit
<< " Intersections: " << step.maneuver.intersections.size() << " [";
for (auto intersection : step.maneuver.intersections)
std::cout << "(" << intersection.duration << " " << intersection.distance << ")";
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
}
}
// Every Step Maneuver consists of the information until the turn.
// This list contains a set of instructions, called silent, which should
// not be part of the final output.
// They are required for maintenance purposes. We can calculate the number
// of exits to pass in a roundabout and the number of intersections
// that we come across.
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
{
// the steps should always include the first/last step in form of a location
BOOST_ASSERT(steps.size() >= 2);
if (steps.size() == 2)
return steps;
#define OSRM_POST_PROCESSING_PRINT_DEBUG 0
#if OSRM_POST_PROCESSING_PRINT_DEBUG
std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
std::cout << "Input\n";
print(leg_data);
print(steps);
#endif
// Count Street Exits forward
bool on_roundabout = false;
for (auto &path_data : leg_data)
// adds an intersection to the initial route step
// It includes the length of the last step, until the intersection
// Also updates the length of the respective segment
auto addIntersection =
[](RouteStep into, const RouteStep &last_step, const RouteStep &intersection)
{
if (not path_data.empty())
path_data[0].exit = carry_exit;
into.maneuver.intersections.push_back(
{last_step.duration, last_step.distance, intersection.maneuver.location});
for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
return detail::forwardInto(std::move(into), intersection);
};
// count the exits forward. if enter/exit roundabout happen both, no further treatment is
// required. We might end up with only one of them (e.g. starting within a roundabout)
// or having a via-point in the roundabout.
// In this case, exits are numbered from the start of the lag.
std::size_t last_valid_instruction = 0;
for (std::size_t step_index = 0; step_index < steps.size(); ++step_index)
{
auto &step = steps[step_index];
const auto instruction = step.maneuver.instruction;
if (entersRoundabout(instruction))
{
if (entersRoundabout(path_data[data_index].turn_instruction))
last_valid_instruction = step_index;
on_roundabout = detail::setUpRoundabout(step);
if (on_roundabout && step_index + 1 < steps.size())
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
}
else if (instruction.type == TurnType::StayOnRoundabout)
{
// increase the exit number we require passing the exit
step.maneuver.exit += 1;
if (step_index + 1 < steps.size())
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
}
else if (leavesRoundabout(instruction))
{
if (!on_roundabout)
{
path_data[data_index].exit += 1;
on_roundabout = true;
// 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;
}
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;
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 PRINT_DEBUG
// unterminated roundabout
// Move backwards through the instructions until the start and remove the exit number
// A roundabout without exit translates to enter-roundabout.
if (on_roundabout)
{
detail::fixFinalRoundabout(steps);
}
// finally clean up the post-processed instructions.
// Remove all invalid instructions from the set of instructions.
// An instruction is invalid, if its NO_TURN and has WaypointType::None.
// Two valid NO_TURNs exist in each leg in the form of Depart/Arrive
// keep valid instructions
const auto not_is_valid = [](const RouteStep &step)
{
return step.maneuver.instruction == TurnInstruction::NO_TURN() &&
step.maneuver.waypoint_type == WaypointType::None;
};
boost::remove_erase_if(steps, not_is_valid);
#if OSRM_POST_PROCESSING_PRINT_DEBUG
std::cout << "Merged\n";
print(leg_data);
print(steps);
#endif
on_roundabout = false;
// Move Roundabout exit numbers to front
for (auto rev_itr = leg_data.rbegin(); rev_itr != leg_data.rend(); ++rev_itr)
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)
{
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;
}
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);
}
#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;
}
}
}
//remove the data fromt the reached-target step again
leg_geometry.segment_offsets.pop_back();
leg_geometry.segment_distances.pop_back();
return leg_data;
return leg_geometry;
}
} // namespace guidance
+45 -5
View File
@@ -1,20 +1,60 @@
#include "engine/hint.hpp"
#include "engine/object_encoder.hpp"
#include "engine/base64.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include <boost/assert.hpp>
#include <iterator>
#include <algorithm>
#include <ostream>
#include <tuple>
namespace osrm
{
namespace engine
{
std::string Hint::ToBase64() const { return encodeBase64(*this); }
bool Hint::IsValid(const util::Coordinate new_input_coordinates,
const datafacade::BaseDataFacade &facade) const
{
auto is_same_input_coordinate = new_input_coordinates.lon == phantom.input_location.lon &&
new_input_coordinates.lat == phantom.input_location.lat;
return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) &&
facade.GetCheckSum() == data_checksum;
}
std::string Hint::ToBase64() const
{
auto base64 = encodeBase64Bytewise(*this);
// Make safe for usage as GET parameter in URLs
std::replace(begin(base64), end(base64), '+', '-');
std::replace(begin(base64), end(base64), '/', '_');
return base64;
}
Hint Hint::FromBase64(const std::string &base64Hint)
{
BOOST_ASSERT_MSG(base64Hint.size() == ENCODED_HINT_SIZE, "Hint has invalid size");
auto decoded = decodeBase64<Hint>(base64Hint);
return decoded;
}
// 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);
}
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,7 +4,6 @@
#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,7 +2,6 @@
#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"
+209 -187
View File
@@ -1,6 +1,13 @@
#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>
@@ -17,89 +24,30 @@ 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;
// 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) :(
// 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-vector-tile
namespace detail_pbf
namespace pbf
{
inline unsigned encode_length(const unsigned len) { return (len << 3u) | 2u; }
}
// Converts a regular WSG84 lon/lat pair into
// a mercator coordinate
inline void lonlat2merc(double &x, double &y)
struct BBox final
{
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)
BBox(const double _minx, const double _miny, const double _maxx, const double _maxy)
: minx(_minx), miny(_miny), maxx(_maxx), maxy(_maxy)
{
}
@@ -113,15 +61,6 @@ 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
{
@@ -131,15 +70,23 @@ struct point_type_i final
const std::int64_t y;
};
using line_type = std::vector<point_type_i>;
using line_typed = std::vector<point_type_d>;
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));
// from mapnik-vector-tile
// Encodes a linestring using protobuf zigzag encoding
inline bool encode_linestring(line_type line,
protozero::packed_field_uint32 &geometry,
std::int32_t &start_x,
std::int32_t &start_y)
inline bool encodeLinestring(const FixedLine &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)
@@ -155,7 +102,7 @@ inline bool encode_linestring(line_type 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;
@@ -168,15 +115,65 @@ inline bool encode_linestring(line_type 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)
{
// Vector tiles are 4096 virtual pixels on each side
const double tile_extent = 4096.0;
using namespace util::coordinate_calculation;
double min_lon, min_lat, max_lon, max_lat;
// Convert the z,x,y mercator tile coordinates into WSG84 lon/lat values
xyz2wsg84(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon, max_lat);
mercator::xyzToWSG84(parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon,
max_lat);
util::Coordinate southwest{util::FloatLongitude(min_lon), util::FloatLatitude(min_lat)};
util::Coordinate northeast{util::FloatLongitude(max_lon), util::FloatLatitude(max_lat)};
@@ -185,13 +182,70 @@ 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
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;
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};
// Protobuf serialized blocks when objects go out of scope, hence
// the extra scoping below.
@@ -263,38 +317,11 @@ 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);
// 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)
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)
{
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
@@ -316,17 +343,39 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
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
std::min(speed_kmh, 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 + forward_datasource); // datasource value offset
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
}
{
// Encode the geometry for the feature
protozero::packed_field_uint32 geometry(feature_writer, 4);
encode_linestring(tile_line, geometry, start_x, start_y);
encodeLinestring(tile_line, geometry, start_x, start_y);
}
};
// If this is a valid forward edge, go ahead and add it to the tile
if (forward_weight != 0 && edge.forward_edge_based_node_id != SPECIAL_NODEID)
{
std::int32_t start_x = 0;
std::int32_t start_y = 0;
// Calculate the speed for this line
std::uint32_t speed_kmh =
static_cast<std::uint32_t>(round(length / forward_weight * 10 * 3.6));
auto tile_line = coordinatesToTileLine(a, b, tile_bbox);
if (!tile_line.empty())
{
encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight],
forward_datasource, start_x, start_y);
}
}
@@ -337,48 +386,15 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
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(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)));
// Calculate the speed for this line
std::uint32_t speed_kmh =
static_cast<std::uint32_t>(round(length / reverse_weight * 10 * 3.6));
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)
auto tile_line = coordinatesToTileLine(b, a, tile_bbox);
if (!tile_line.empty())
{
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);
encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight],
reverse_datasource, start_x, start_y);
}
}
}
@@ -390,18 +406,17 @@ 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);
@@ -415,12 +430,19 @@ 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));
}
// 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.);
}
}
+1 -13
View File
@@ -135,19 +135,7 @@ InternalRouteResult TripPlugin::ComputeRoute(const std::vector<PhantomNode> &sna
}
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size());
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);
shortest_path(min_route.segment_end_coordinates, parameters.uturns, min_route);
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
return min_route;
-1
View File
@@ -1,7 +1,6 @@
#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"
+37 -33
View File
@@ -12,6 +12,7 @@
#include "extractor/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <algorithm>
#include <cmath>
@@ -34,12 +35,13 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
SpeedProfileProperties speed_profile)
ProfileProperties profile_properties,
const util::NameTable &name_table)
: m_max_edge_id(0), m_node_info_list(node_info_list),
m_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),
speed_profile(std::move(speed_profile))
profile_properties(std::move(profile_properties)), name_table(name_table)
{
}
@@ -123,10 +125,9 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
// traverse arrays from start and end respectively
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);
@@ -207,7 +208,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 + speed_profile.u_turn_penalty);
m_edge_based_node_weights.push_back(edge_data.distance + profile_properties.u_turn_penalty);
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
edge_data.edge_id = numbered_edges_count;
@@ -276,6 +277,9 @@ 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;
@@ -292,8 +296,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
edge_penalty_file.open(edge_fixed_penalties_filename.c_str(), std::ios::binary);
}
// writes a dummy value that is updated later
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
// 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));
std::vector<OriginalEdgeData> original_edge_data_vector;
original_edge_data_vector.reserve(1024 * 1024);
@@ -302,8 +308,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// Three nested loop look super-linear, but we are dealing with a (kind of)
// 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 );
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
m_barrier_nodes, m_compressed_edge_container, name_table);
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
// progress.printStatus(node_u);
@@ -315,15 +321,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
}
++node_based_edge_counter;
auto turn_candidates = turn_analysis.getTurns(node_u, edge_from_u);
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
for (const auto turn : turn_candidates)
for (const auto turn : possible_turns)
{
if (!turn.valid)
continue;
const double turn_angle = turn.angle;
// only add an edge if turn is not prohibited
@@ -338,15 +341,15 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
unsigned distance = edge_data1.distance;
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
{
distance += speed_profile.traffic_signal_penalty;
distance += profile_properties.traffic_signal_penalty;
}
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
const int turn_penalty = use_turn_function ? GetTurnPenalty(turn_angle, lua_state) : 0;
const auto turn_instruction = turn.instruction;
if (guidance::isUturn(turn_instruction))
{
distance += speed_profile.u_turn_penalty;
distance += profile_properties.u_turn_penalty;
}
distance += turn_penalty;
@@ -422,8 +425,13 @@ 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);
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
const auto length_prefix = boost::numeric_cast<unsigned>(original_edges_counter);
static_assert(sizeof(length_prefix_empty_space) == sizeof(length_prefix), "type mismatch");
edge_data_file.write(reinterpret_cast<const char *>(&length_prefix), sizeof(length_prefix));
util::SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
<< " edge based nodes";
@@ -441,20 +449,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
{
if (speed_profile.has_turn_penalty_function)
BOOST_ASSERT(lua_state != nullptr);
try
{
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();
}
// 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();
}
return 0;
}
+3 -1
View File
@@ -288,6 +288,8 @@ 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
@@ -323,7 +325,7 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
edge_iterator->source_coordinate,
util::Coordinate(node_iterator->lon, node_iterator->lat));
if (util::lua_function_exists(segment_state, "segment_function"))
if (has_segment_function)
{
luabind::call_function<void>(
segment_state, "segment_function", boost::cref(edge_iterator->source_coordinate),
+35 -66
View File
@@ -15,6 +15,7 @@
#include "util/timing_util.hpp"
#include "util/lua_util.hpp"
#include "util/graph_loader.hpp"
#include "util/name_table.hpp"
#include "util/typedefs.hpp"
@@ -47,6 +48,7 @@
#include <unordered_map>
#include <vector>
#include <bitset>
#include <chrono>
namespace osrm
{
@@ -74,6 +76,9 @@ namespace extractor
*/
int Extractor::run()
{
// setup scripting environment
ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
try
{
util::LogPolicy::GetInstance().Unmute();
@@ -88,9 +93,6 @@ 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);
@@ -106,15 +108,12 @@ int Extractor::run()
util::SimpleLogger().Write() << "Parsing in progress..";
TIMER_START(parsing);
lua_State *segment_state = scripting_environment.GetLuaState();
auto& main_context = scripting_environment.GetContex();
if (util::lua_function_exists(segment_state, "source_function"))
// setup raster sources
if (util::luaFunctionExists(main_context.state, "source_function"))
{
// bind a single instance of SourceContainer class to relevant lua state
SourceContainer sources;
luabind::globals(segment_state)["sources"] = sources;
luabind::call_function<void>(segment_state, "source_function");
luabind::call_function<void>(main_context.state, "source_function");
}
std::string generator = header.get("generator");
@@ -141,7 +140,7 @@ int Extractor::run()
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
// setup restriction parser
const RestrictionParser restriction_parser(scripting_environment.GetLuaState());
const RestrictionParser restriction_parser(main_context.state, main_context.properties);
while (const osmium::memory::Buffer buffer = reader.read())
{
@@ -164,7 +163,7 @@ int Extractor::run()
{
ExtractionNode result_node;
ExtractionWay result_way;
lua_State *local_state = scripting_environment.GetLuaState();
auto& local_context = scripting_environment.GetContex();
for (auto x = range.begin(), end = range.end(); x != end; ++x)
{
@@ -176,7 +175,7 @@ int Extractor::run()
result_node.clear();
++number_of_nodes;
luabind::call_function<void>(
local_state, "node_function",
local_context.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));
@@ -185,7 +184,7 @@ int Extractor::run()
result_way.clear();
++number_of_ways;
luabind::call_function<void>(
local_state, "way_function",
local_context.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));
@@ -237,26 +236,29 @@ int Extractor::run()
}
extraction_containers.PrepareData(config.output_file_name, config.restriction_file_name,
config.names_file_name, segment_state);
config.names_file_name, main_context.state);
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
TIMER_STOP(extracting);
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
//
//
// // Create a new lua state
auto& main_context = scripting_environment.GetContex();
util::SimpleLogger().Write() << "Generating edge-expanded graph representation";
@@ -267,7 +269,9 @@ 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(internal_to_external_node_map,
auto graph_size = BuildEdgeExpandedGraph(main_context.state,
main_context.properties,
internal_to_external_node_map,
edge_based_node_list, node_is_startpoint,
edge_based_node_weights, edge_based_edge_list);
@@ -313,46 +317,15 @@ int Extractor::run()
return 0;
}
/**
\brief Setups scripting environment (lua-scripting)
Also initializes speed profile.
*/
void Extractor::SetupScriptingEnvironment(lua_State *lua_state,
SpeedProfileProperties &speed_profile)
void Extractor::WriteProfileProperties(const std::string& output_path, const ProfileProperties& properties) const
{
// 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()))
boost::filesystem::ofstream out_stream(output_path);
if (!out_stream)
{
std::stringstream msg;
msg << lua_tostring(lua_state, -1) << " occurred in scripting block";
throw util::exception(msg.str());
throw util::exception("Could not open " + output_path + " for writing.");
}
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");
out_stream.write(reinterpret_cast<const char*>(&properties), sizeof(properties));
}
void Extractor::FindComponents(unsigned max_edge_id,
@@ -495,18 +468,14 @@ Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
\brief Building an edge-expanded graph from node-based input and turn restrictions
*/
std::pair<std::size_t, std::size_t>
Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
Extractor::BuildEdgeExpandedGraph(lua_State* lua_state,
const ProfileProperties& profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<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;
@@ -515,23 +484,23 @@ Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_n
LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map);
CompressedEdgeContainer compressed_edge_container;
GraphCompressor graph_compressor(speed_profile);
GraphCompressor graph_compressor;
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, speed_profile);
internal_to_external_node_map, profile_properties, name_table);
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,11 +13,6 @@ 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
+4 -23
View File
@@ -1,5 +1,5 @@
#include "extractor/restriction_parser.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/external_memory_node.hpp"
#include "util/lua_util.hpp"
@@ -33,37 +33,18 @@ int luaErrorCallback(lua_State *lua_state)
}
}
RestrictionParser::RestrictionParser(lua_State *lua_state) : use_turn_restrictions(true)
RestrictionParser::RestrictionParser(lua_State *lua_state, const ProfileProperties &properties)
: use_turn_restrictions(properties.use_turn_restrictions)
{
ReadUseRestrictionsSetting(lua_state);
if (use_turn_restrictions)
{
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::lua_function_exists(lua_state, "get_exceptions"))
if (util::luaFunctionExists(lua_state, "get_exceptions"))
{
luabind::set_pcall_callback(&luaErrorCallback);
// get list of turn restriction exceptions
+93 -82
View File
@@ -6,7 +6,9 @@
#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"
@@ -56,117 +58,126 @@ ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) : file_
util::SimpleLogger().Write() << "Using script " << file_name;
}
void ScriptingEnvironment::InitLuaState(lua_State *lua_state)
void ScriptingEnvironment::InitContext(ScriptingEnvironment::Context &context)
{
typedef double (osmium::Location::*location_member_ptr_type)() const;
luabind::open(lua_state);
luabind::open(context.state);
// open utility libraries string library;
luaL_openlibs(lua_state);
luaL_openlibs(context.state);
util::luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
util::luaAddScriptFolderToLoadPath(context.state, file_name.c_str());
// Add our function to the state's global scope
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::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::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_<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_<osmium::Location>("Location")
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
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::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::Location>("Location")
.def<location_member_ptr_type>("lat", &osmium::Location::lat)
.def<location_member_ptr_type>("lon", &osmium::Location::lon),
luabind::class_<ExtractionNode>("ResultNode")
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
.def_readwrite("barrier", &ExtractionNode::barrier),
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_<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_<ExtractionNode>("ResultNode")
.def_readwrite("traffic_lights", &ExtractionNode::traffic_lights)
.def_readwrite("barrier", &ExtractionNode::barrier),
if (0 != luaL_dofile(lua_state, file_name.c_str()))
luabind::class_<ExtractionWay>("ResultWay")
// .def(luabind::constructor<>())
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted)
.def_readwrite("is_startpoint", &ExtractionWay::is_startpoint)
.def_readwrite("duration", &ExtractionWay::duration)
.property("forward_mode", &ExtractionWay::get_forward_mode,
&ExtractionWay::set_forward_mode)
.property("backward_mode", &ExtractionWay::get_backward_mode,
&ExtractionWay::set_backward_mode),
luabind::class_<osmium::Way>("Way")
.def("get_value_by_key", &osmium::Way::get_value_by_key)
.def("get_value_by_key", &get_value_by_key<osmium::Way>)
.def("id", &osmium::Way::id),
luabind::class_<InternalExtractorEdge>("EdgeSource")
.def_readonly("source_coordinate", &InternalExtractorEdge::source_coordinate)
.def_readwrite("weight_data", &InternalExtractorEdge::weight_data),
luabind::class_<InternalExtractorEdge::WeightData>("WeightData")
.def_readwrite("speed", &InternalExtractorEdge::WeightData::speed),
luabind::class_<ExternalMemoryNode>("EdgeTarget")
.property("lon", &lonToDouble<ExternalMemoryNode>)
.property("lat", &latToDouble<ExternalMemoryNode>),
luabind::class_<util::Coordinate>("Coordinate")
.property("lon", &lonToDouble<util::Coordinate>)
.property("lat", &latToDouble<util::Coordinate>),
luabind::class_<RasterDatum>("RasterDatum")
.def_readonly("datum", &RasterDatum::datum)
.def("invalid_data", &RasterDatum::get_invalid)];
luabind::globals(context.state)["properties"] = &context.properties;
luabind::globals(context.state)["sources"] = &context.sources;
if (0 != luaL_dofile(context.state, file_name.c_str()))
{
luabind::object error_msg(luabind::from_stack(lua_state, -1));
luabind::object error_msg(luabind::from_stack(context.state, -1));
std::ostringstream error_stream;
error_stream << error_msg;
throw util::exception("ERROR occurred in profile script:\n" + error_stream.str());
}
}
lua_State *ScriptingEnvironment::GetLuaState()
ScriptingEnvironment::Context &ScriptingEnvironment::GetContex()
{
std::lock_guard<std::mutex> lock(init_mutex);
bool initialized = false;
auto &ref = script_contexts.local(initialized);
if (!initialized)
{
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
ref = state;
InitLuaState(ref.get());
ref = util::make_unique<Context>();
InitContext(*ref);
}
luabind::set_pcall_callback(&luaErrorCallback);
return ref.get();
return *ref;
}
}
}
+1 -3
View File
@@ -25,9 +25,7 @@ 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) ||
constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "uturns",
parameters.uturns, coord_size, help);
parameters.radiuses, coord_size, help);
if (!param_size_mismatch && parameters.coordinates.size() < 2)
{
+69 -128
View File
@@ -2,6 +2,7 @@
#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"
@@ -72,10 +73,12 @@ void deleteRegion(const SharedDataType region)
}
}
Storage::Storage(const DataPaths &paths_) : paths(paths_) {}
Storage::Storage(StorageConfig config_) : config(std::move(config_)) {}
int Storage::Run()
{
BOOST_ASSERT_MSG(config.IsValid(), "Invalid storage config");
util::LogPolicy::GetInstance().Unmute();
SharedBarriers barrier;
@@ -99,94 +102,6 @@ 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 = [&]
@@ -209,14 +124,19 @@ 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,
file_index_path.length() + 1);
absolute_file_index_path.string().length() + 1);
// collect number of elements to store in shared memory object
util::SimpleLogger().Write() << "load names from: " << names_data_path;
util::SimpleLogger().Write() << "load names from: " << config.names_data_path;
// number of entries in name index
boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
boost::filesystem::ifstream name_stream(config.names_data_path, std::ios::binary);
if (!name_stream)
{
throw util::exception("Could not open " + config.names_data_path.string() + " for reading.");
}
unsigned name_blocks = 0;
name_stream.read((char *)&name_blocks, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
@@ -230,7 +150,11 @@ int Storage::Run()
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
// Loading information for original edges
boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
if (!edges_input_stream)
{
throw util::exception("Could not open " + config.edges_data_path.string() + " for reading.");
}
unsigned number_of_original_edges = 0;
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
@@ -244,7 +168,11 @@ int Storage::Run()
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
boost::filesystem::ifstream hsgr_input_stream(config.hsgr_data_path, std::ios::binary);
if (!hsgr_input_stream)
{
throw util::exception("Could not open " + config.hsgr_data_path.string() + " for reading.");
}
util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
util::FingerPrint fingerprint_loaded;
@@ -279,39 +207,27 @@ int Storage::Run()
number_of_graph_edges);
// load rsearch tree size
boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
boost::filesystem::ifstream tree_node_file(config.ram_index_path, std::ios::binary);
uint32_t tree_size = 0;
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;
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);
}
getline(timestamp_stream, m_timestamp);
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
// load core marker size
boost::filesystem::ifstream core_marker_file(core_marker_path, std::ios::binary);
boost::filesystem::ifstream core_marker_file(config.core_data_path, std::ios::binary);
if (!core_marker_file)
{
throw util::exception("Could not open " + config.core_data_path.string() + " for reading.");
}
uint32_t number_of_core_markers = 0;
core_marker_file.read((char *)&number_of_core_markers, sizeof(uint32_t));
@@ -319,14 +235,22 @@ int Storage::Run()
number_of_core_markers);
// load coordinate size
boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
boost::filesystem::ifstream nodes_input_stream(config.nodes_data_path, std::ios::binary);
if (!nodes_input_stream)
{
throw util::exception("Could not open " + config.core_data_path.string() + " for reading.");
}
unsigned coordinate_list_size = 0;
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
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(), std::ios::binary);
boost::filesystem::ifstream geometry_input_stream(config.geometries_path, std::ios::binary);
if (!geometry_input_stream)
{
throw util::exception("Could not open " + config.geometries_path.string() + " for reading.");
}
unsigned number_of_geometries_indices = 0;
unsigned number_of_compressed_geometries = 0;
@@ -341,8 +265,12 @@ int Storage::Run()
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
// exist.
std::ifstream geometry_datasource_input_stream(datasource_indexes_path.c_str(),
std::ios::binary);
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::size_t number_of_compressed_datasources = 0;
if (geometry_datasource_input_stream)
{
@@ -354,7 +282,12 @@ int Storage::Run()
// Load datasource name sizes. This file is optional, and it's non-fatal if it doesn't
// exist
std::ifstream datasource_names_input_stream(datasource_names_path.c_str(), std::ios::binary);
boost::filesystem::ifstream datasource_names_input_stream(config.datasource_names_path,
std::ios::binary);
if (!datasource_names_input_stream)
{
throw util::exception("Could not open " + config.datasource_names_path.string() + " for reading.");
}
std::vector<char> m_datasource_name_data;
std::vector<std::size_t> m_datasource_name_offsets;
std::vector<std::size_t> m_datasource_name_lengths;
@@ -370,11 +303,11 @@ int Storage::Run()
}
}
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::DATASOURCE_NAME_DATA,
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 "
@@ -397,7 +330,7 @@ int Storage::Run()
file_index_path_ptr +
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
0);
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
std::copy(absolute_file_index_path.string().begin(), absolute_file_index_path.string().end(), file_index_path_ptr);
// Loading street names
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
@@ -504,8 +437,7 @@ 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);
@@ -605,6 +537,15 @@ 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
@@ -0,0 +1,38 @@
#include "storage/storage_config.hpp"
#include <boost/filesystem/operations.hpp>
namespace osrm
{
namespace storage
{
StorageConfig::StorageConfig(const boost::filesystem::path &base)
: ram_index_path{base.string() + ".ramIndex"}, file_index_path{base.string() + ".fileIndex"},
hsgr_data_path{base.string() + ".hsgr"}, nodes_data_path{base.string() + ".nodes"},
edges_data_path{base.string() + ".edges"}, core_data_path{base.string() + ".core"},
geometries_path{base.string() + ".geometry"}, timestamp_path{base.string() + ".timestamp"},
datasource_names_path{base.string() + ".datasource_names"},
datasource_indexes_path{base.string() + ".datasource_indexes"},
names_data_path{base.string() + ".names"},
properties_path{base.string() + ".properties"}
{
}
bool StorageConfig::IsValid() const
{
return boost::filesystem::is_regular_file(ram_index_path) &&
boost::filesystem::is_regular_file(file_index_path) &&
boost::filesystem::is_regular_file(hsgr_data_path) &&
boost::filesystem::is_regular_file(nodes_data_path) &&
boost::filesystem::is_regular_file(edges_data_path) &&
boost::filesystem::is_regular_file(core_data_path) &&
boost::filesystem::is_regular_file(geometries_path) &&
boost::filesystem::is_regular_file(timestamp_path) &&
boost::filesystem::is_regular_file(datasource_names_path) &&
boost::filesystem::is_regular_file(datasource_indexes_path) &&
boost::filesystem::is_regular_file(names_data_path) &&
boost::filesystem::is_regular_file(properties_path);
}
}
}
+132 -5
View File
@@ -1,10 +1,14 @@
#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>
@@ -19,6 +23,7 @@
#include <iostream>
#include <new>
#include <thread>
#include <string>
#ifdef _WIN32
boost::function0<void> console_ctrl_function;
@@ -41,6 +46,111 @@ 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();
@@ -50,19 +160,36 @@ int main(int argc, const char *argv[]) try
int ip_port, requested_thread_num;
EngineConfig config;
const unsigned init_result = util::GenerateServerProgramOptions(
argc, argv, config.server_paths, ip_address, ip_port, requested_thread_num,
boost::filesystem::path base_path;
const unsigned init_result = generateServerProgramOptions(
argc, argv, base_path, ip_address, ip_port, requested_thread_num,
config.use_shared_memory, trial_run, config.max_locations_trip,
config.max_locations_viaroute, config.max_locations_distance_table,
config.max_locations_map_matching);
if (init_result == util::INIT_OK_DO_NOT_START_ENGINE)
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
{
return EXIT_SUCCESS;
}
if (init_result == util::INIT_FAILED)
if (init_result == 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
+11 -157
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[], storage::DataPaths &paths)
bool generateDataStoreOptions(const int argc, const char *argv[], boost::filesystem::path& base_path)
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
@@ -20,36 +20,11 @@ bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataP
// declare a group of options that will be allowed both on command line
// 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>(&paths["base"]),
"base,b", boost::program_options::value<boost::filesystem::path>(&base_path),
"base path to .osrm file");
// positional option
@@ -93,132 +68,6 @@ bool generateDataStoreOptions(const int argc, const char *argv[], storage::DataP
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;
}
@@ -226,13 +75,18 @@ int main(const int argc, const char *argv[]) try
{
util::LogPolicy::GetInstance().Unmute();
storage::DataPaths paths;
if (!generateDataStoreOptions(argc, argv, paths))
boost::filesystem::path base_path;
if (!generateDataStoreOptions(argc, argv, base_path))
{
return EXIT_SUCCESS;
}
storage::Storage storage(paths);
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));
return storage.Run();
}
catch (const std::bad_alloc &e)
-14
View File
@@ -29,20 +29,6 @@ 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
+80 -18
View File
@@ -4,7 +4,6 @@
#include "util/trigonometry_table.hpp"
#include <boost/assert.hpp>
#include <boost/math/constants/constants.hpp>
#include <cmath>
@@ -14,6 +13,7 @@ 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 * (RAD);
const double dlat1 = lt1 * DEGREE_TO_RAD;
const double dlong1 = ln1 * (RAD);
const double dlat2 = lt2 * (RAD);
const double dlong2 = ln2 * (RAD);
const double dlong1 = ln1 * DEGREE_TO_RAD;
const double dlat2 = lt2 * DEGREE_TO_RAD;
const double dlong2 = ln2 * DEGREE_TO_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) * 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 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 x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
const double y_value = float_lat2 - float_lat1;
@@ -269,22 +269,84 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
namespace mercator
{
FloatLatitude yToLat(const double value)
FloatLatitude yToLat(const double y)
{
using namespace boost::math::constants;
const double normalized_lat = RAD_TO_DEGREE * 2. * std::atan(std::exp(y * DEGREE_TO_RAD));
return FloatLatitude(
180. * (1. / pi<long double>()) *
(2. * std::atan(std::exp(value * pi<double>() / 180.)) - half_pi<double>()));
return FloatLatitude(normalized_lat - 90.);
}
double latToY(const FloatLatitude latitude)
{
using namespace boost::math::constants;
const double normalized_lat = 90. + static_cast<double>(latitude);
return 180. * (1. / pi<double>()) *
std::log(std::tan((pi<double>() / 4.) +
static_cast<double>(latitude) * (pi<double>() / 180.) / 2.));
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;
}
} // ns mercato // ns mercatorr
+62
View File
@@ -0,0 +1,62 @@
#include "util/name_table.hpp"
#include "util/simple_logger.hpp"
#include "util/exception.hpp"
#include <algorithm>
#include <limits>
#include <fstream>
#include <boost/filesystem/fstream.hpp>
namespace osrm
{
namespace util
{
NameTable::NameTable(const std::string &filename)
{
boost::filesystem::ifstream name_stream(filename, std::ios::binary);
if( !name_stream )
throw exception("Failed to open " + filename + " for reading.");
name_stream >> m_name_table;
unsigned number_of_chars = 0;
name_stream.read(reinterpret_cast<char *>(&number_of_chars), sizeof(number_of_chars));
if( !name_stream )
throw exception("Encountered invalid file, failed to read number of contained chars");
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read(reinterpret_cast<char *>(&m_names_char_list[0]),
number_of_chars * sizeof(m_names_char_list[0]));
if( !name_stream )
throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from file.");
if (0 == m_names_char_list.size())
{
util::SimpleLogger().Write(logWARNING) << "list of street names is empty";
}
}
std::string NameTable::GetNameForID(const unsigned name_id) const
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
return "";
}
auto range = m_name_table.GetRange(name_id);
std::string result;
result.reserve(range.size());
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_names_char_list.begin() + range.front(),
m_names_char_list.begin() + range.back() + 1, result.begin());
}
return result;
}
} // namespace util
} // namespace osrm
+74
View File
@@ -0,0 +1,74 @@
#include "engine/base64.hpp"
#include "engine/hint.hpp"
#include "mocks/mock_datafacade.hpp"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <iostream>
#include <algorithm>
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
BOOST_AUTO_TEST_SUITE(base64)
// For test vectors see section 10: https://tools.ietf.org/html/rfc4648#section-10
BOOST_AUTO_TEST_CASE(rfc4648_test_vectors)
{
using namespace osrm::engine;
BOOST_CHECK_EQUAL(encodeBase64(""), "");
BOOST_CHECK_EQUAL(encodeBase64("f"), "Zg==");
BOOST_CHECK_EQUAL(encodeBase64("fo"), "Zm8=");
BOOST_CHECK_EQUAL(encodeBase64("foo"), "Zm9v");
BOOST_CHECK_EQUAL(encodeBase64("foob"), "Zm9vYg==");
BOOST_CHECK_EQUAL(encodeBase64("fooba"), "Zm9vYmE=");
BOOST_CHECK_EQUAL(encodeBase64("foobar"), "Zm9vYmFy");
}
BOOST_AUTO_TEST_CASE(rfc4648_test_vectors_roundtrip)
{
using namespace osrm::engine;
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("")), "");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("f")), "f");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fo")), "fo");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foo")), "foo");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foob")), "foob");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fooba")), "fooba");
BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foobar")), "foobar");
}
BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip)
{
using namespace osrm::engine;
osrm::test::MockDataFacade facade;
Hint hint{{}, {}, facade.GetCheckSum()};
const auto base64 = hint.ToBase64();
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '+'));
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '/'));
const auto decoded = Hint::FromBase64(base64);
BOOST_CHECK_EQUAL(hint, decoded);
}
BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip_bytewise)
{
using namespace osrm::engine;
osrm::test::MockDataFacade facade;
Hint hint{{}, {}, facade.GetCheckSum()};
const auto decoded = Hint::FromBase64(hint.ToBase64());
BOOST_CHECK(std::equal(reinterpret_cast<const unsigned char *>(&hint),
reinterpret_cast<const unsigned char *>(&hint) + sizeof(Hint),
reinterpret_cast<const unsigned char *>(&decoded)));
}
BOOST_AUTO_TEST_SUITE_END()
+1
View File
@@ -103,6 +103,7 @@ class MockDataFacadeT final : public osrm::engine::datafacade::BaseDataFacade<Ed
std::string get_name_for_id(const unsigned /* name_id */) const { return ""; }
std::size_t GetCoreSize() const { return 0; }
std::string GetTimestamp() const { return ""; }
bool GetUTurnsDefault() const override { return true; }
};
using MockDataFacade = MockDataFacadeT<contractor::QueryEdge::EdgeData>;
+14 -13
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);
CHECK_EQUAL_RANGE(reference_1.uturns, result_1->uturns);
BOOST_CHECK_EQUAL(reference_1.uturns, result_1->uturns);
CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
@@ -146,25 +146,26 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_2.alternatives, result_2->alternatives);
BOOST_CHECK_EQUAL(reference_2.geometries, result_2->geometries);
BOOST_CHECK_EQUAL(reference_2.overview, result_2->overview);
CHECK_EQUAL_RANGE(reference_2.uturns, result_2->uturns);
BOOST_CHECK_EQUAL(reference_2.uturns, result_2->uturns);
CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
std::vector<boost::optional<bool>> uturns_3 = {true, false, boost::none};
engine::api::RouteParameters reference_3{
false, false, engine::api::RouteParameters::GeometriesType::GeoJSON,
engine::api::RouteParameters::OverviewType::False, uturns_3};
engine::api::RouteParameters reference_3{false,
false,
engine::api::RouteParameters::GeometriesType::GeoJSON,
engine::api::RouteParameters::OverviewType::False,
true};
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);
CHECK_EQUAL_RANGE(reference_3.uturns, result_3->uturns);
BOOST_CHECK_EQUAL(reference_3.uturns, result_3->uturns);
CHECK_EQUAL_RANGE(reference_3.bearings, result_3->bearings);
CHECK_EQUAL_RANGE(reference_3.radiuses, result_3->radiuses);
CHECK_EQUAL_RANGE(reference_3.coordinates, result_3->coordinates);
@@ -180,7 +181,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true,
engine::api::RouteParameters::GeometriesType::Polyline,
engine::api::RouteParameters::OverviewType::Simplified,
std::vector<boost::optional<bool>>{},
boost::optional<bool>{},
coords_1,
hints_4,
std::vector<boost::optional<double>>{},
@@ -196,7 +197,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
BOOST_CHECK_EQUAL(reference_4.geometries, result_4->geometries);
BOOST_CHECK_EQUAL(reference_4.overview, result_4->overview);
CHECK_EQUAL_RANGE(reference_4.uturns, result_4->uturns);
BOOST_CHECK_EQUAL(reference_4.uturns, result_4->uturns);
CHECK_EQUAL_RANGE(reference_4.bearings, result_4->bearings);
CHECK_EQUAL_RANGE(reference_4.radiuses, result_4->radiuses);
CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates);
@@ -208,7 +209,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true,
engine::api::RouteParameters::GeometriesType::Polyline,
engine::api::RouteParameters::OverviewType::Simplified,
std::vector<boost::optional<bool>>{},
boost::optional<bool>{},
coords_1,
std::vector<boost::optional<engine::Hint>>{},
std::vector<boost::optional<double>>{},
@@ -220,7 +221,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_5.alternatives, result_5->alternatives);
BOOST_CHECK_EQUAL(reference_5.geometries, result_5->geometries);
BOOST_CHECK_EQUAL(reference_5.overview, result_5->overview);
CHECK_EQUAL_RANGE(reference_5.uturns, result_5->uturns);
BOOST_CHECK_EQUAL(reference_5.uturns, result_5->uturns);
CHECK_EQUAL_RANGE(reference_5.bearings, result_5->bearings);
CHECK_EQUAL_RANGE(reference_5.radiuses, result_5->radiuses);
CHECK_EQUAL_RANGE(reference_5.coordinates, result_5->coordinates);
@@ -238,7 +239,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK_EQUAL(reference_6.alternatives, result_6->alternatives);
BOOST_CHECK_EQUAL(reference_6.geometries, result_6->geometries);
BOOST_CHECK_EQUAL(reference_6.overview, result_6->overview);
CHECK_EQUAL_RANGE(reference_6.uturns, result_6->uturns);
BOOST_CHECK_EQUAL(reference_6.uturns, result_6->uturns);
CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
+66
View File
@@ -24,3 +24,69 @@ 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
@@ -1,83 +0,0 @@
#include "util/tiles.hpp"
using namespace osrm::util;
#include <boost/functional/hash.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <iostream>
BOOST_AUTO_TEST_SUITE(tiles_test)
using namespace osrm;
using namespace osrm::util;
BOOST_AUTO_TEST_CASE(point_to_tile_test)
{
tiles::Tile tile_1_reference{2306375680, 1409941503, 32};
tiles::Tile tile_2_reference{2308259840, 1407668224, 32};
tiles::Tile tile_3_reference{616562688, 2805989376, 32};
tiles::Tile tile_4_reference{1417674752, 2084569088, 32};
tiles::Tile tile_5_reference{616562688, 2805989376, 32};
tiles::Tile tile_6_reference{712654285, 2671662374, 32};
auto tile_1 =
tiles::pointToTile(FloatLongitude(13.31817626953125), FloatLatitude(52.449314140869696));
auto tile_2 =
tiles::pointToTile(FloatLongitude(13.476104736328125), FloatLatitude(52.56529070208021));
auto tile_3 =
tiles::pointToTile(FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186));
auto tile_4 =
tiles::pointToTile(FloatLongitude(-61.17187499999999), FloatLatitude(5.266007882805498));
auto tile_5 =
tiles::pointToTile(FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186));
auto tile_6 =
tiles::pointToTile(FloatLongitude(-120.266007882805532), FloatLatitude(-40.17187499999999));
BOOST_CHECK_EQUAL(tile_1.x, tile_1_reference.x);
BOOST_CHECK_EQUAL(tile_1.y, tile_1_reference.y);
BOOST_CHECK_EQUAL(tile_1.z, tile_1_reference.z);
BOOST_CHECK_EQUAL(tile_2.x, tile_2_reference.x);
BOOST_CHECK_EQUAL(tile_2.y, tile_2_reference.y);
BOOST_CHECK_EQUAL(tile_2.z, tile_2_reference.z);
BOOST_CHECK_EQUAL(tile_3.x, tile_3_reference.x);
BOOST_CHECK_EQUAL(tile_3.y, tile_3_reference.y);
BOOST_CHECK_EQUAL(tile_3.z, tile_3_reference.z);
BOOST_CHECK_EQUAL(tile_4.x, tile_4_reference.x);
BOOST_CHECK_EQUAL(tile_4.y, tile_4_reference.y);
BOOST_CHECK_EQUAL(tile_4.z, tile_4_reference.z);
BOOST_CHECK_EQUAL(tile_5.x, tile_5_reference.x);
BOOST_CHECK_EQUAL(tile_5.y, tile_5_reference.y);
BOOST_CHECK_EQUAL(tile_5.z, tile_5_reference.z);
BOOST_CHECK_EQUAL(tile_6.x, tile_6_reference.x);
BOOST_CHECK_EQUAL(tile_6.y, tile_6_reference.y);
BOOST_CHECK_EQUAL(tile_6.z, tile_6_reference.z);
}
// Verify that the bearing-bounds checking function behaves as expected
BOOST_AUTO_TEST_CASE(bounding_box_to_tile_test)
{
tiles::Tile tile_1_reference{17, 10, 5};
tiles::Tile tile_2_reference{0, 0, 0};
tiles::Tile tile_3_reference{0, 2, 2};
auto tile_1 = tiles::getBBMaxZoomTile(
FloatLongitude(13.31817626953125), FloatLatitude(52.449314140869696),
FloatLongitude(13.476104736328125), FloatLatitude(52.56529070208021));
auto tile_2 = tiles::getBBMaxZoomTile(
FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186),
FloatLongitude(-61.17187499999999), FloatLatitude(5.266007882805498));
auto tile_3 = tiles::getBBMaxZoomTile(
FloatLongitude(-128.32031249999997), FloatLatitude(-48.224672649565186),
FloatLongitude(-120.2660078828055), FloatLatitude(-40.17187499999999));
BOOST_CHECK_EQUAL(tile_1.x, tile_1_reference.x);
BOOST_CHECK_EQUAL(tile_1.y, tile_1_reference.y);
BOOST_CHECK_EQUAL(tile_1.z, tile_1_reference.z);
BOOST_CHECK_EQUAL(tile_2.x, tile_2_reference.x);
BOOST_CHECK_EQUAL(tile_2.y, tile_2_reference.y);
BOOST_CHECK_EQUAL(tile_2.z, tile_2_reference.z);
BOOST_CHECK_EQUAL(tile_3.x, tile_3_reference.x);
BOOST_CHECK_EQUAL(tile_3.y, tile_3_reference.y);
BOOST_CHECK_EQUAL(tile_3.z, tile_3_reference.z);
}
BOOST_AUTO_TEST_SUITE_END()
+25
View File
@@ -0,0 +1,25 @@
#include "util/viewport.hpp"
using namespace osrm::util;
#include <boost/functional/hash.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <iostream>
BOOST_AUTO_TEST_SUITE(viewport_test)
using namespace osrm;
using namespace osrm::util;
BOOST_AUTO_TEST_CASE(zoom_level_test)
{
BOOST_CHECK_EQUAL(
viewport::getFittedZoom(
Coordinate(FloatLongitude{5.668343999999995}, FloatLatitude{45.111511000000014}),
Coordinate(FloatLongitude{5.852471999999996}, FloatLatitude{45.26800200000002})),
12);
}
BOOST_AUTO_TEST_SUITE_END()