[osrm] 02/07: Imported Upstream version 4.7.0
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat Aug 22 19:42:33 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository osrm.
commit 3d1b3188669c69d362a3e7f6d6fe4dead9ebdaf5
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sat Aug 22 20:03:20 2015 +0200
Imported Upstream version 4.7.0
---
.gitignore | 4 +
.travis.yml | 3 +-
CMakeLists.txt | 8 +-
Gemfile.lock | 27 +-
README.md | 31 +-
algorithms/polyline_compressor.cpp | 38 +
algorithms/polyline_compressor.hpp | 4 +
algorithms/tiny_components.hpp | 2 +-
appveyor-build.bat | 113 +++
appveyor.yml | 43 +-
build-local.bat | 19 +
contractor/contractor.hpp | 5 +-
contractor/contractor_options.cpp | 135 ++++
.../contractor_options.hpp | 27 +-
contractor/edge_based_graph_factory.cpp | 90 ++-
contractor/edge_based_graph_factory.hpp | 17 +-
contractor/processing_chain.cpp | 507 +++++--------
contractor/processing_chain.hpp | 58 +-
data_structures/dynamic_graph.hpp | 3 +
data_structures/import_edge.cpp | 7 +
data_structures/import_edge.hpp | 5 +-
data_structures/node_based_graph.hpp | 268 +++----
data_structures/restriction_map.hpp | 7 +-
data_structures/route_parameters.cpp | 8 +
data_structures/static_rtree.hpp | 39 +-
datastore.cpp | 5 +-
descriptors/description_factory.cpp | 7 +-
extract.cpp | 2 +-
extractor/extraction_containers.cpp | 841 +++++++++++++--------
extractor/extraction_containers.hpp | 17 +-
extractor/extraction_helper_functions.hpp | 2 +-
extractor/extractor.cpp | 21 +-
extractor/extractor.hpp | 9 +-
extractor/extractor_callbacks.cpp | 74 +-
extractor/extractor_options.cpp | 4 +
extractor/extractor_options.hpp | 1 +
extractor/internal_extractor_edge.hpp | 112 +--
extractor/restriction_parser.cpp | 2 +-
extractor/scripting_environment.cpp | 2 +-
features/bicycle/access.feature | 6 +-
features/bicycle/access_node.feature | 35 +-
features/bicycle/surface.feature | 2 +-
features/car/maxspeed.feature | 19 +
features/car/names.feature | 10 +-
features/foot/access.feature | 4 +-
features/foot/access_node.feature | 4 +-
features/foot/surface.feature | 2 +-
features/foot/way.feature | 6 +
features/nearest/pick.feature | 20 +-
features/options/prepare/help.feature | 2 +-
features/step_definitions/data.rb | 4 +
features/step_definitions/distance_matrix.rb | 2 +-
features/step_definitions/locate.rb | 4 +-
features/step_definitions/matching.rb | 2 +-
features/step_definitions/nearest.rb | 4 +-
features/step_definitions/routability.rb | 2 +-
features/step_definitions/routing.rb | 2 +-
features/support/cucumber.rb | 76 --
features/support/env.rb | 10 +-
features/support/hooks.rb | 16 +-
features/support/http.rb | 34 +
features/support/locate.rb | 17 +-
features/support/match.rb | 12 +-
features/support/nearest.rb | 17 +-
features/support/route.rb | 14 +-
features/testbot/ferry.feature | 30 +
features/testbot/loop.feature | 19 +
features/testbot/post.feature | 100 +++
features/testbot/snap.feature | 42 +-
features/testbot/via.feature | 22 +-
include/osrm/route_parameters.hpp | 2 +
prepare.cpp | 70 +-
profiles/bicycle.lua | 123 +--
profiles/car.lua | 60 +-
profiles/foot.lua | 291 +++----
profiles/lib/access.lua | 8 +-
profiles/lib/maxspeed.lua | 6 +-
routing_algorithms/alternative_path.hpp | 4 +-
routing_algorithms/shortest_path.hpp | 6 +-
server/api_grammar.hpp | 7 +-
server/request_parser.cpp | 71 +-
server/request_parser.hpp | 8 +-
tools/components.cpp | 142 ++--
tools/graph_compare.cpp | 199 -----
unit_tests/algorithms/duration_parsing.cpp | 24 +-
unit_tests/algorithms/geometry_string.cpp | 74 ++
util/fingerprint.hpp | 13 +-
util/fingerprint_impl.hpp.in | 45 +-
util/graph_loader.hpp | 444 ++---------
util/iso_8601_duration_parser.hpp | 2 +-
util/lua_util.hpp | 5 +-
91 files changed, 2460 insertions(+), 2250 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6ed5d2a..6264b42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+# pre compiled dependencies #
+#############################
+osrm-deps
+
# Compiled source #
###################
*.com
diff --git a/.travis.yml b/.travis.yml
index ed023e4..55e7190 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,6 +30,7 @@ script:
- make
- make tests
- make benchmarks
+ - ./algorithm-tests
- ./datastructure-tests
- cd ..
- cucumber -p verify
@@ -58,7 +59,7 @@ notifications:
skip_join: false
recipients:
- - dennis at mapbox.com
+ - patrick at mapbox.com
email:
on_success: change
on_failure: always
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 503171a..80eb3d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -90,7 +90,7 @@ set(
add_library(COORDINATE OBJECT ${CoordinateGlob})
add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
-add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
+add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR> $<TARGET_OBJECTS:IMPORT>)
add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
add_dependencies(FINGERPRINT FingerPrintConfigure)
@@ -328,12 +328,10 @@ if(WITH_TOOLS OR BUILD_TOOLS)
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
- add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
- target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
+ add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:IMPORT>)
+ target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES} ${TBB_LIBRARIES})
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
- add_executable(osrm-graph-compare tools/graph_compare.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
- target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES})
install(TARGETS osrm-cli DESTINATION bin)
install(TARGETS osrm-io-benchmark DESTINATION bin)
diff --git a/Gemfile.lock b/Gemfile.lock
index ac056a0..3363e92 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,22 +2,27 @@ GEM
remote: http://rubygems.org/
specs:
builder (3.2.2)
- cucumber (1.3.8)
+ cucumber (2.0.0)
builder (>= 2.1.2)
+ cucumber-core (~> 1.1.3)
diff-lcs (>= 1.1.3)
- gherkin (~> 2.12.1)
+ gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
- multi_test (>= 0.0.2)
- diff-lcs (1.2.4)
- gherkin (2.12.1)
+ multi_test (>= 0.1.2)
+ cucumber-core (1.1.3)
+ gherkin (~> 2.12.0)
+ diff-lcs (1.2.5)
+ gherkin (2.12.2)
multi_json (~> 1.3)
- multi_json (1.8.0)
- multi_test (0.0.2)
+ multi_json (1.11.0)
+ multi_test (0.1.2)
osmlib-base (0.1.4)
- rake (10.1.0)
- rspec-expectations (2.14.3)
- diff-lcs (>= 1.1.3, < 2.0)
- sys-proctable (0.9.3)
+ rake (10.4.2)
+ rspec-expectations (3.2.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.2.0)
+ rspec-support (3.2.2)
+ sys-proctable (0.9.8)
PLATFORMS
ruby
diff --git a/README.md b/README.md
index 624cc1d..d319d26 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,25 @@
-# Readme
+## About
-For instructions on how to compile and run OSRM, please consult the Wiki at
+The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.
-https://github.com/Project-OSRM/osrm-backend/wiki
+## Current build status
+
+| build config | branch | status |
+|:-------------|:--------|:------------|
+| Linux | master | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
+| Linux | develop | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
+| Windows | master/develop | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
+| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
+
+## Building
+
+For instructions on how to [build](https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM) and [run OSRM](https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM), please consult [the Wiki](https://github.com/Project-OSRM/osrm-backend/wiki).
-or use our free and daily updated online service at
+To quickly try OSRM use our [free and daily updated online service](http://map.project-osrm.org)
-http://map.project-osrm.org
+## Documentation
+
+See the Wiki's [server API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Server-api) as well as the [library API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Library-api)
## References in publications
@@ -31,11 +44,3 @@ When using the code in a (scientific) publication, please cite
}
```
-## Current build status
-
-| build config | branch | status |
-|:-------------|:--------|:------------|
-| Linux | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
-| Linux | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
-| Windows | master/develop | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
-| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp
index d5fd582..0db75dc 100644
--- a/algorithms/polyline_compressor.cpp
+++ b/algorithms/polyline_compressor.cpp
@@ -88,3 +88,41 @@ PolylineCompressor::get_encoded_string(const std::vector<SegmentInformation> &po
}
return encode_vector(delta_numbers);
}
+
+std::vector<FixedPointCoordinate> PolylineCompressor::decode_string(const std::string &geometry_string) const
+{
+ std::vector<FixedPointCoordinate> new_coordinates;
+ int index = 0, len = geometry_string.size();
+ int lat = 0, lng = 0;
+
+ while (index < len)
+ {
+ int b, shift = 0, result = 0;
+ do
+ {
+ b = geometry_string.at(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lat += dlat;
+
+ shift = 0;
+ result = 0;
+ do
+ {
+ b = geometry_string.at(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lng += dlng;
+
+ FixedPointCoordinate p;
+ p.lat = COORDINATE_PRECISION * (((double) lat / 1E6));
+ p.lon = COORDINATE_PRECISION * (((double) lng / 1E6));
+ new_coordinates.push_back(p);
+ }
+
+ return new_coordinates;
+}
diff --git a/algorithms/polyline_compressor.hpp b/algorithms/polyline_compressor.hpp
index 933ac7a..a148200 100644
--- a/algorithms/polyline_compressor.hpp
+++ b/algorithms/polyline_compressor.hpp
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct SegmentInformation;
+#include <osrm/coordinate.hpp>
+
#include <string>
#include <vector>
@@ -42,6 +44,8 @@ class PolylineCompressor
public:
std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
+
+ std::vector<FixedPointCoordinate> decode_string(const std::string &geometry_string) const;
};
#endif /* POLYLINECOMPRESSOR_H_ */
diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp
index 8eb61a9..8abc1cb 100644
--- a/algorithms/tiny_components.hpp
+++ b/algorithms/tiny_components.hpp
@@ -150,7 +150,7 @@ template <typename GraphT> class TarjanSCC
// Traverse outgoing edges
if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime)
{
- // continue;
+ continue;
}
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
diff --git a/appveyor-build.bat b/appveyor-build.bat
new file mode 100644
index 0000000..eef29b1
--- /dev/null
+++ b/appveyor-build.bat
@@ -0,0 +1,113 @@
+ at ECHO OFF
+SETLOCAL
+SET EL=0
+
+ECHO platform^: %platform%
+:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
+SET DEPSPKG=osrm-deps-win-x64-14.0.7z
+
+:: local development
+IF "%computername%"=="MB" GOTO SKIPDL
+
+IF EXIST %DEPSPKG% DEL %DEPSPKG%
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO downloading %DEPSPKG%
+powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-deps/$env:DEPSPKG -OutFile C:\projects\osrm\$env:DEPSPKG
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+7z -y x %DEPSPKG% | %windir%\system32\FIND "ing archive"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+:SKIPDL
+
+IF EXIST build rd /s /q build
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+mkdir build
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+cd build
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+SET OSRMDEPSDIR=c:\projects\osrm\osrm-deps
+set PREFIX=%OSRMDEPSDIR%/libs
+set BOOST_ROOT=%OSRMDEPSDIR%/boost
+set TBB_INSTALL_DIR=%OSRMDEPSDIR%/tbb
+set TBB_ARCH_PLATFORM=intel64/vc14
+
+ECHO calling cmake ....
+cmake .. ^
+-G "Visual Studio 14 Win64" ^
+-DBOOST_ROOT=%BOOST_ROOT% ^
+-DBoost_ADDITIONAL_VERSIONS=1.57 ^
+-DBoost_USE_MULTITHREADED=ON ^
+-DBoost_USE_STATIC_LIBS=ON ^
+-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
+-DCMAKE_INSTALL_PREFIX=%PREFIX%
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO building ...
+msbuild OSRM.sln ^
+/p:Configuration=%Configuration% ^
+/p:Platform=x64 ^
+/t:rebuild ^
+/p:BuildInParallel=true ^
+/m:%NUMBER_OF_PROCESSORS% ^
+/toolsversion:14.0 ^
+/p:PlatformToolset=v140 ^
+/clp:Verbosity=normal ^
+/nologo ^
+/flp1:logfile=build_errors.txt;errorsonly ^
+/flp2:logfile=build_warnings.txt;warningsonly
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO ========= TODO^: CREATE PACKAGES ==========
+
+CD c:\projects\osrm\build\%Configuration%
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+SET PATH=c:\projects\osrm\osrm-deps\libs\bin;%PATH%
+
+ECHO running datastructure-tests.exe ...
+datastructure-tests.exe
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+ECHO running algorithm-tests.exe ...
+algorithm-tests.exe
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+GOTO DONE
+
+:ERROR
+SET EL=%ERRORLEVEL%
+ECHO ============== ERROR ===============
+
+:DONE
+ECHO ============= DONE ===============
+CD C:\projects\osrm
+EXIT /b %EL%
+
+
+
+
+ - cd c:/projects/osrm
+ - mkdir build
+ - cd build
+ - echo Running cmake...
+ - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
+ - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
+ - SET P=c:/projects/osrm
+ - set TBB_INSTALL_DIR=%P%/tbb
+ - set TBB_ARCH_PLATFORM=intel64/vc12
+ - cmake .. -G "Visual Studio 14 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON
+ - SET PLATFORM_TOOLSET=v140
+ - SET TOOLS_VERSION=14.0
+ - msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo OSRM.sln
+ - msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo tests.vcxproj
+ - cd %Configuration%
+ - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
+ - cd ..\..\profiles
+ - echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
+ - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
+ - set PATH=%PATH%;c:/projects/osrm/libs/bin
+ - cd c:/projects/osrm/build/%Configuration%
+ - datastructure-tests.exe
+ - algorithm-tests.exe
diff --git a/appveyor.yml b/appveyor.yml
index afb8dd4..cf45a32 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,60 +1,33 @@
environment:
matrix:
- - configuration: Debug
- configuration: Release
-
-# branches to build
-branches:
- # whitelist
- only:
- - develop
+# - configuration: Debug
# scripts that are called at very beginning, before repo cloning
init:
- git config --global core.autocrlf input
+os: Visual Studio 2015 RC
+
# clone directory
clone_folder: c:\projects\osrm
platform: x64
install:
- # by default, all script lines are interpreted as batch
- - nuget install protobuf
- - cd c:\projects\osrm
- - curl -O http://build.project-osrm.org/libs_osrm_%Configuration%.7z
- - 7z x libs_osrm_%Configuration%.7z | find ":"
+ - set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
+ - CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
build_script:
- - cd c:/projects/osrm
- - mkdir build
- - cd build
- - echo Running cmake...
- - call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
- - SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
- - SET P=c:/projects/osrm
- - set TBB_INSTALL_DIR=%P%/tbb
- - set TBB_ARCH_PLATFORM=intel64/vc12
- - cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013
- - msbuild /clp:Verbosity=minimal /nologo OSRM.sln
- - msbuild /clp:Verbosity=minimal /nologo tests.vcxproj
- - cd %Configuration%
- - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
- - cd ..\..\profiles
- - echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
- - if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
- - set PATH=%PATH%;c:/projects/osrm/libs/bin
- - cd c:/projects/osrm/build/%Configuration%
- - datastructure-tests.exe
- - algorithm-tests.exe
+ - CALL appveyor-build.bat
test: off
artifacts:
- - path: osrm_Debug.zip
- name: osrm_Debug.zip
- path: osrm_Release.zip
name: osrm_Release.zip
+# - path: osrm_Debug.zip
+# name: osrm_Debug.zip
deploy:
provider: FTP
diff --git a/build-local.bat b/build-local.bat
new file mode 100644
index 0000000..47a1fb3
--- /dev/null
+++ b/build-local.bat
@@ -0,0 +1,19 @@
+ at ECHO OFF
+
+SET PLATFORM=x64
+SET CONFIGURATION=Release
+
+WHERE msbuild
+IF %ERRORLEVEL% EQU 0 GOTO RUNBUILD
+
+SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.1.0-win32-x86\bin;%PATH%
+SET PATH=C:\Program Files\7-Zip;%PATH%
+ECHO activating VS command prompt ...
+SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
+CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+
+:RUNBUILD
+
+powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
+CALL appveyor-build.bat
+EXIT /b %ERRORLEVEL%
diff --git a/contractor/contractor.hpp b/contractor/contractor.hpp
index ccfabbc..4468f5e 100644
--- a/contractor/contractor.hpp
+++ b/contractor/contractor.hpp
@@ -171,7 +171,8 @@ class Contractor
{
SimpleLogger().Write(logWARNING)
<< "Edge weight large -> "
- << static_cast<unsigned int>(std::max(diter->weight, 1));
+ << static_cast<unsigned int>(std::max(diter->weight, 1)) << " : "
+ << static_cast<unsigned int>(diter->source) << " -> " << static_cast<unsigned int>(diter->target);
}
#endif
edges.emplace_back(diter->source, diter->target,
@@ -186,6 +187,7 @@ class Contractor
}
// clear input vector
input_edge_list.clear();
+ // FIXME not sure if we need this
edges.shrink_to_fit();
tbb::parallel_sort(edges.begin(), edges.end());
@@ -953,7 +955,6 @@ class Contractor
}
std::shared_ptr<ContractorGraph> contractor_graph;
- std::vector<ContractorGraph::InputEdge> contracted_edge_list;
stxxl::vector<QueryEdge> external_edge_list;
std::vector<NodeID> orig_node_id_to_new_id_map;
XORFastHash fast_hash;
diff --git a/contractor/contractor_options.cpp b/contractor/contractor_options.cpp
new file mode 100644
index 0000000..eaa1ba9
--- /dev/null
+++ b/contractor/contractor_options.cpp
@@ -0,0 +1,135 @@
+/*
+
+Copyright (c) 2015, 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.
+
+*/
+
+#include "contractor_options.hpp"
+
+#include "../util/git_sha.hpp"
+#include "../util/simple_logger.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
+
+#include <tbb/task_scheduler_init.h>
+
+return_code
+ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &contractor_config)
+{
+ // 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", boost::program_options::value<boost::filesystem::path>(&contractor_config.config_file_path)
+ ->default_value("contractor.ini"),
+ "Path to a configuration file.");
+
+ // declare a group of options that will be allowed both on command line and in config file
+ boost::program_options::options_description config_options("Configuration");
+ config_options.add_options()(
+ "restrictions,r",
+ boost::program_options::value<boost::filesystem::path>(&contractor_config.restrictions_path),
+ "Restrictions file in .osrm.restrictions format")(
+ "profile,p", boost::program_options::value<boost::filesystem::path>(&contractor_config.profile_path)
+ ->default_value("profile.lua"),
+ "Path to LUA routing profile")(
+ "threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
+ ->default_value(tbb::task_scheduler_init::default_num_threads()),
+ "Number of threads to use");
+
+ // hidden options, will be allowed both on command line and in config file, but will not be
+ // shown to the user
+ boost::program_options::options_description hidden_options("Hidden options");
+ hidden_options.add_options()(
+ "input,i", boost::program_options::value<boost::filesystem::path>(&contractor_config.osrm_input_path),
+ "Input file in .osm, .osm.bz2 or .osm.pbf format");
+
+ // positional option
+ boost::program_options::positional_options_description positional_options;
+ positional_options.add("input", 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 config_file_options;
+ config_file_options.add(config_options).add(hidden_options);
+
+ boost::program_options::options_description visible_options(
+ "Usage: " + boost::filesystem::basename(argv[0]) + " <input.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);
+
+ const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
+ if (boost::filesystem::is_regular_file(temp_config_path))
+ {
+ boost::program_options::store(boost::program_options::parse_config_file<char>(
+ temp_config_path.string().c_str(), cmdline_options, true),
+ option_variables);
+ }
+
+ if (option_variables.count("version"))
+ {
+ SimpleLogger().Write() << g_GIT_DESCRIPTION;
+ return return_code::exit;
+ }
+
+ if (option_variables.count("help"))
+ {
+ SimpleLogger().Write() << "\n" << visible_options;
+ return return_code::exit;
+ }
+
+ boost::program_options::notify(option_variables);
+
+ if (!option_variables.count("restrictions"))
+ {
+ contractor_config.restrictions_path = contractor_config.osrm_input_path.string() + ".restrictions";
+ }
+
+ if (!option_variables.count("input"))
+ {
+ SimpleLogger().Write() << "\n" << visible_options;
+ return return_code::fail;
+ }
+
+ return return_code::ok;
+}
+
+void ContractorOptions::GenerateOutputFilesNames(ContractorConfig &contractor_config)
+{
+ contractor_config.node_output_path = contractor_config.osrm_input_path.string() + ".nodes";
+ contractor_config.edge_output_path = contractor_config.osrm_input_path.string() + ".edges";
+ contractor_config.geometry_output_path = contractor_config.osrm_input_path.string() + ".geometry";
+ contractor_config.graph_output_path = contractor_config.osrm_input_path.string() + ".hsgr";
+ contractor_config.rtree_nodes_output_path = contractor_config.osrm_input_path.string() + ".ramIndex";
+ contractor_config.rtree_leafs_output_path = contractor_config.osrm_input_path.string() + ".fileIndex";
+}
diff --git a/extractor/extractor_options.hpp b/contractor/contractor_options.hpp
similarity index 70%
copy from extractor/extractor_options.hpp
copy to contractor/contractor_options.hpp
index 5712ea0..87541af 100644
--- a/extractor/extractor_options.hpp
+++ b/contractor/contractor_options.hpp
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef EXTRACTOR_OPTIONS_HPP
-#define EXTRACTOR_OPTIONS_HPP
+#ifndef CONTRACTOR_OPTIONS_HPP
+#define CONTRACTOR_OPTIONS_HPP
#include <boost/filesystem/path.hpp>
@@ -39,25 +39,30 @@ enum class return_code : unsigned
exit
};
-struct ExtractorConfig
+struct ContractorConfig
{
- ExtractorConfig() noexcept : requested_num_threads(0) {}
+ ContractorConfig() noexcept : requested_num_threads(0) {}
+
boost::filesystem::path config_file_path;
- boost::filesystem::path input_path;
+ boost::filesystem::path osrm_input_path;
+ boost::filesystem::path restrictions_path;
boost::filesystem::path profile_path;
- std::string output_file_name;
- std::string restriction_file_name;
- std::string timestamp_file_name;
+ std::string node_output_path;
+ std::string edge_output_path;
+ std::string geometry_output_path;
+ std::string graph_output_path;
+ std::string rtree_nodes_output_path;
+ std::string rtree_leafs_output_path;
unsigned requested_num_threads;
};
-struct ExtractorOptions
+struct ContractorOptions
{
- static return_code ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config);
+ static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config);
- static void GenerateOutputFilesNames(ExtractorConfig &extractor_config);
+ static void GenerateOutputFilesNames(ContractorConfig &extractor_config);
};
#endif // EXTRACTOR_OPTIONS_HPP
diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp
index 268bb9f..dbd73a7 100644
--- a/contractor/edge_based_graph_factory.cpp
+++ b/contractor/edge_based_graph_factory.cpp
@@ -40,21 +40,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iomanip>
#include <limits>
-EdgeBasedGraphFactory::EdgeBasedGraphFactory(
- const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
- std::unique_ptr<RestrictionMap> restriction_map,
- std::vector<NodeID> &barrier_node_list,
- std::vector<NodeID> &traffic_light_node_list,
- std::vector<QueryNode> &node_info_list,
- SpeedProfileProperties &speed_profile)
+EdgeBasedGraphFactory::EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
+ std::shared_ptr<RestrictionMap> restriction_map,
+ std::unique_ptr<std::vector<NodeID>> barrier_node_list,
+ std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
+ const std::vector<QueryNode> &node_info_list,
+ const SpeedProfileProperties &speed_profile)
: speed_profile(speed_profile),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
- m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
+ m_node_info_list(node_info_list),
+ m_node_based_graph(std::move(node_based_graph)),
m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
{
// insert into unordered sets for fast lookup
- m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end());
- m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end());
+ m_barrier_nodes.insert(barrier_node_list->begin(), barrier_node_list->end());
+ m_traffic_lights.insert(traffic_light_node_list->begin(), traffic_light_node_list->end());
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
@@ -193,15 +193,16 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
{
BOOST_ASSERT(forward_data.forward);
}
- if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
+ else
{
- BOOST_ASSERT(reverse_data.forward);
+ BOOST_ASSERT(!forward_data.forward);
}
- if (forward_data.edgeBasedNodeID == SPECIAL_NODEID)
+
+ if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
{
- BOOST_ASSERT(!forward_data.forward);
+ BOOST_ASSERT(reverse_data.forward);
}
- if (reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
+ else
{
BOOST_ASSERT(!reverse_data.forward);
}
@@ -233,7 +234,6 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
const std::string &geometry_filename,
lua_State *lua_state)
{
-
TIMER_START(geometry);
CompressGeometry();
TIMER_STOP(geometry);
@@ -290,12 +290,33 @@ void EdgeBasedGraphFactory::CompressGeometry()
continue;
}
+ /*
+ * reverse_e2 forward_e2
+ * u <---------- v -----------> w
+ * ----------> <-----------
+ * forward_e1 reverse_e1
+ *
+ * Will be compressed to:
+ *
+ * reverse_e1
+ * u <---------- w
+ * ---------->
+ * forward_e1
+ *
+ * If the edges are compatible.
+ *
+ */
+
const bool reverse_edge_order =
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
+ BOOST_ASSERT(forward_e2 >= m_node_based_graph->BeginEdges(node_v) &&
+ forward_e2 < m_node_based_graph->EndEdges(node_v));
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
+ BOOST_ASSERT(reverse_e2 >= m_node_based_graph->BeginEdges(node_v) &&
+ reverse_e2 < m_node_based_graph->EndEdges(node_v));
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
@@ -322,9 +343,20 @@ void EdgeBasedGraphFactory::CompressGeometry()
continue;
}
- if ( // TODO: rename to IsCompatibleTo
- fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2))
+ // this case can happen if two ways with different names overlap
+ if (fwd_edge_data1.nameID != rev_edge_data1.nameID ||
+ fwd_edge_data2.nameID != rev_edge_data2.nameID)
{
+ continue;
+ }
+
+ if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2))
+ {
+ BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
+ m_node_based_graph->GetEdgeData(reverse_e1).nameID);
+ BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e2).nameID ==
+ m_node_based_graph->GetEdgeData(reverse_e2).nameID);
+
// Get distances before graph is modified
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
@@ -336,7 +368,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
BOOST_ASSERT(0 != reverse_weight1);
- BOOST_ASSERT(0 != forward_weight2);
+ BOOST_ASSERT(0 != reverse_weight2);
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
@@ -362,11 +394,11 @@ void EdgeBasedGraphFactory::CompressGeometry()
// update any involved turn restrictions
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
- m_node_based_graph);
+ *m_node_based_graph);
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
- m_node_based_graph);
+ *m_node_based_graph);
// store compressed geometry in container
m_geometry_compressor.CompressEdge(
@@ -378,8 +410,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
++removed_node_count;
- BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
- m_node_based_graph->GetEdgeData(reverse_e1).nameID);
+
}
}
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
@@ -403,18 +434,19 @@ void EdgeBasedGraphFactory::CompressGeometry()
<< new_edge_count / (double)original_number_of_edges;
}
-/**
- * Writes the id of the edge in the edge expanded graph (into the edge in the node based graph)
- */
+/// Renumbers all _forward_ edges and sets the edgeBasedNodeID.
+/// A specific numbering is not important. Any unique ID will do.
void EdgeBasedGraphFactory::RenumberEdges()
{
- // renumber edge based node IDs
+ // renumber edge based node of outgoing edges
unsigned numbered_edges_count = 0;
for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
{
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
+
+ // this edge is an incoming edge
if (!edge_data.forward)
{
continue;
@@ -466,7 +498,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
const NodeID node_v = m_node_based_graph->GetTarget(e1);
BOOST_ASSERT(SPECIAL_NODEID != node_v);
- // pick only every other edge
+ // pick only every other edge, since we have every edge as an outgoing
+ // and incoming egde
if (node_u > node_v)
{
continue;
@@ -492,6 +525,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
const bool component_is_tiny = size_of_component < 1000;
+ // we only set edgeBasedNodeID for forward edges
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
{
InsertEdgeBasedNode(node_v, node_u,
diff --git a/contractor/edge_based_graph_factory.hpp b/contractor/edge_based_graph_factory.hpp
index 95b65ba..a527439 100644
--- a/contractor/edge_based_graph_factory.hpp
+++ b/contractor/edge_based_graph_factory.hpp
@@ -59,12 +59,12 @@ class EdgeBasedGraphFactory
struct SpeedProfileProperties;
- explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
- std::unique_ptr<RestrictionMap> restricion_map,
- std::vector<NodeID> &barrier_node_list,
- std::vector<NodeID> &traffic_light_node_list,
- std::vector<QueryNode> &node_info_list,
- SpeedProfileProperties &speed_profile);
+ explicit EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
+ std::shared_ptr<RestrictionMap> restricion_map,
+ std::unique_ptr<std::vector<NodeID>> barrier_node_list,
+ std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
+ const std::vector<QueryNode> &node_info_list,
+ const SpeedProfileProperties &speed_profile);
void Run(const std::string &original_edge_data_filename,
const std::string &geometry_filename,
@@ -97,15 +97,16 @@ class EdgeBasedGraphFactory
unsigned m_number_of_edge_based_nodes;
- std::vector<QueryNode> m_node_info_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
+ const std::vector<QueryNode>& m_node_info_list;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
+ std::shared_ptr<RestrictionMap> m_restriction_map;
+
std::unordered_set<NodeID> m_barrier_nodes;
std::unordered_set<NodeID> m_traffic_lights;
- std::unique_ptr<RestrictionMap> m_restriction_map;
GeometryCompressor m_geometry_compressor;
diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp
index ccff7fd..a76bc65 100644
--- a/contractor/processing_chain.cpp
+++ b/contractor/processing_chain.cpp
@@ -48,7 +48,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/filesystem/fstream.hpp>
#include <boost/program_options.hpp>
-#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_sort.h>
#include <chrono>
@@ -57,166 +56,98 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <thread>
#include <vector>
-Prepare::Prepare() : requested_num_threads(1) {}
-
Prepare::~Prepare() {}
-int Prepare::Process(int argc, char *argv[])
+int Prepare::Run()
{
- LogPolicy::GetInstance().Unmute();
- TIMER_START(preparing);
- TIMER_START(expansion);
-
- if (!ParseArguments(argc, argv))
- {
- return 0;
- }
- if (!boost::filesystem::is_regular_file(input_path))
- {
- SimpleLogger().Write(logWARNING) << "Input file " << input_path.string() << " not found!";
- return 1;
- }
-
- if (!boost::filesystem::is_regular_file(profile_path))
- {
- SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string() << " not found!";
- return 1;
- }
-
- if (1 > requested_num_threads)
- {
- SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
- return 1;
- }
-
- const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
-
- SimpleLogger().Write() << "Input file: " << input_path.filename().string();
- SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
- SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
- SimpleLogger().Write() << "Threads: " << requested_num_threads;
- if (recommended_num_threads != requested_num_threads)
- {
- SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
- << recommended_num_threads
- << "! This setting may have performance side-effects.";
- }
-
- tbb::task_scheduler_init init(requested_num_threads);
-
- LogPolicy::GetInstance().Unmute();
-
- FingerPrint fingerprint_orig;
- CheckRestrictionsFile(fingerprint_orig);
-
- boost::filesystem::ifstream input_stream(input_path, std::ios::in | std::ios::binary);
-
- node_filename = input_path.string() + ".nodes";
- edge_out = input_path.string() + ".edges";
- geometry_filename = input_path.string() + ".geometry";
- graph_out = input_path.string() + ".hsgr";
- rtree_nodes_path = input_path.string() + ".ramIndex";
- rtree_leafs_path = input_path.string() + ".fileIndex";
-
- /*** Setup Scripting Environment ***/
- // Create a new lua state
- lua_State *lua_state = luaL_newstate();
-
- // Connect LuaBind to this lua state
- luabind::open(lua_state);
-
- EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
-
- if (!SetupScriptingEnvironment(lua_state, speed_profile))
- {
- return 1;
- }
-
#ifdef WIN32
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
#else
- static_assert(sizeof(ImportEdge) == 20,
- "changing ImportEdge type has influence on memory consumption!");
+ static_assert(sizeof(NodeBasedEdge) == 20,
+ "changing NodeBasedEdge type has influence on memory consumption!");
+ static_assert(sizeof(EdgeBasedEdge) == 16,
+ "changing EdgeBasedEdge type has influence on memory consumption!");
#endif
- NodeID number_of_node_based_nodes = readBinaryOSRMGraphFromStream(
- input_stream, edge_list, barrier_node_list, traffic_light_list,
- &internal_to_external_node_map, restriction_list);
- input_stream.close();
- if (edge_list.empty())
- {
- SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
- return 1;
- }
+ TIMER_START(preparing);
- SimpleLogger().Write() << restriction_list.size() << " restrictions, "
- << barrier_node_list.size() << " bollard nodes, "
- << traffic_light_list.size() << " traffic lights";
+ // Create a new lua state
- std::vector<EdgeBasedNode> node_based_edge_list;
- unsigned number_of_edge_based_nodes = 0;
+ SimpleLogger().Write() << "Generating edge-expanded graph representation";
+
+ TIMER_START(expansion);
+
+ auto node_based_edge_list = osrm::make_unique<std::vector<EdgeBasedNode>>();;
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
+ auto internal_to_external_node_map = osrm::make_unique<std::vector<QueryNode>>();
+ auto graph_size =
+ BuildEdgeExpandedGraph(*internal_to_external_node_map,
+ *node_based_edge_list, edge_based_edge_list);
- // init node_based_edge_list, edge_based_edge_list by edgeList
- number_of_edge_based_nodes =
- BuildEdgeExpandedGraph(lua_state, number_of_node_based_nodes, node_based_edge_list,
- edge_based_edge_list, speed_profile);
- lua_close(lua_state);
+ auto number_of_node_based_nodes = graph_size.first;
+ auto number_of_edge_based_nodes = graph_size.second;
TIMER_STOP(expansion);
- BuildRTree(node_based_edge_list);
-
- RangebasedCRC32 crc32;
- if (crc32.using_hardware())
- {
- SimpleLogger().Write() << "using hardware based CRC32 computation";
- }
- else
- {
- SimpleLogger().Write() << "using software based CRC32 computation";
- }
+ SimpleLogger().Write() << "building r-tree ...";
+ TIMER_START(rtree);
- const unsigned crc32_value = crc32(node_based_edge_list);
- node_based_edge_list.clear();
- node_based_edge_list.shrink_to_fit();
- SimpleLogger().Write() << "CRC32: " << crc32_value;
+ BuildRTree(*node_based_edge_list, *internal_to_external_node_map);
- WriteNodeMapping();
+ TIMER_STOP(rtree);
- /***
- * Contracting the edge-expanded graph
- */
+ SimpleLogger().Write() << "writing node map ...";
+ WriteNodeMapping(std::move(internal_to_external_node_map));
- SimpleLogger().Write() << "initializing contractor";
- auto contractor =
- osrm::make_unique<Contractor>(number_of_edge_based_nodes, edge_based_edge_list);
+ // Contracting the edge-expanded graph
TIMER_START(contraction);
- contractor->Run();
+ auto contracted_edge_list = osrm::make_unique<DeallocatingVector<QueryEdge>>();
+ ContractGraph(number_of_edge_based_nodes, edge_based_edge_list, *contracted_edge_list);
TIMER_STOP(contraction);
SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
- DeallocatingVector<QueryEdge> contracted_edge_list;
- contractor->GetEdges(contracted_edge_list);
- contractor.reset();
+ std::size_t number_of_used_edges = WriteContractedGraph(number_of_edge_based_nodes,
+ std::move(node_based_edge_list),
+ std::move(contracted_edge_list));
- /***
- * Sorting contracted edges in a way that the static query graph can read some in in-place.
- */
+ TIMER_STOP(preparing);
- tbb::parallel_sort(contracted_edge_list.begin(), contracted_edge_list.end());
- const unsigned contracted_edge_count = contracted_edge_list.size();
+ SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
+ SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
+ << " nodes/sec and "
+ << (number_of_edge_based_nodes / TIMER_SEC(expansion)) << " edges/sec";
+
+ SimpleLogger().Write() << "Contraction: "
+ << (number_of_edge_based_nodes / TIMER_SEC(contraction))
+ << " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
+ << " edges/sec";
+
+ SimpleLogger().Write() << "finished preprocessing";
+
+ return 0;
+}
+
+std::size_t Prepare::WriteContractedGraph(unsigned number_of_edge_based_nodes,
+ std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
+ std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list)
+{
+ const unsigned crc32_value = CalculateEdgeChecksum(std::move(node_based_edge_list));
+
+ // Sorting contracted edges in a way that the static query graph can read some in in-place.
+ tbb::parallel_sort(contracted_edge_list->begin(), contracted_edge_list->end());
+ const unsigned contracted_edge_count = contracted_edge_list->size();
SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
<< " edges";
- boost::filesystem::ofstream hsgr_output_stream(graph_out, std::ios::binary);
- hsgr_output_stream.write((char *)&fingerprint_orig, sizeof(FingerPrint));
+ const FingerPrint fingerprint = FingerPrint::GetValid();
+ boost::filesystem::ofstream hsgr_output_stream(config.graph_output_path, std::ios::binary);
+ hsgr_output_stream.write((char *)&fingerprint, sizeof(FingerPrint));
const unsigned max_used_node_id = 1 + [&contracted_edge_list]
{
unsigned tmp_max = 0;
- for (const QueryEdge &edge : contracted_edge_list)
+ for (const QueryEdge &edge : *contracted_edge_list)
{
BOOST_ASSERT(SPECIAL_NODEID != edge.source);
BOOST_ASSERT(SPECIAL_NODEID != edge.target);
@@ -241,7 +172,7 @@ int Prepare::Process(int argc, char *argv[])
for (const auto node : osrm::irange(0u, max_used_node_id))
{
last_edge = edge;
- while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
+ while ((edge < contracted_edge_count) && ((*contracted_edge_list)[edge].source == node))
{
++edge;
}
@@ -270,19 +201,19 @@ int Prepare::Process(int argc, char *argv[])
hsgr_output_stream.write((char *)&node_array[0],
sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
}
- // serialize all edges
+ // serialize all edges
SimpleLogger().Write() << "Building edge array";
edge = 0;
int number_of_used_edges = 0;
StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
- for (const auto edge : osrm::irange<std::size_t>(0, contracted_edge_list.size()))
+ for (const auto edge : osrm::irange<std::size_t>(0, contracted_edge_list->size()))
{
// no eigen loops
- BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
- current_edge.target = contracted_edge_list[edge].target;
- current_edge.data = contracted_edge_list[edge].data;
+ BOOST_ASSERT((*contracted_edge_list)[edge].source != (*contracted_edge_list)[edge].target);
+ current_edge.target = (*contracted_edge_list)[edge].target;
+ current_edge.data = (*contracted_edge_list)[edge].data;
// every target needs to be valid
BOOST_ASSERT(current_edge.target < max_used_node_id);
@@ -290,12 +221,12 @@ int Prepare::Process(int argc, char *argv[])
if (current_edge.data.distance <= 0)
{
SimpleLogger().Write(logWARNING) << "Edge: " << edge
- << ",source: " << contracted_edge_list[edge].source
- << ", target: " << contracted_edge_list[edge].target
+ << ",source: " << (*contracted_edge_list)[edge].source
+ << ", target: " << (*contracted_edge_list)[edge].target
<< ", dist: " << current_edge.data.distance;
SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
- << contracted_edge_list[edge].source << "/"
+ << (*contracted_edge_list)[edge].source << "/"
<< node_array.size() - 1;
return 1;
}
@@ -305,170 +236,54 @@ int Prepare::Process(int argc, char *argv[])
++number_of_used_edges;
}
- hsgr_output_stream.close();
- TIMER_STOP(preparing);
-
- SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
- SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
- << " nodes/sec and "
- << (number_of_edge_based_nodes / TIMER_SEC(expansion)) << " edges/sec";
-
- SimpleLogger().Write() << "Contraction: "
- << (number_of_edge_based_nodes / TIMER_SEC(contraction))
- << " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
- << " edges/sec";
-
- node_array.clear();
- SimpleLogger().Write() << "finished preprocessing";
-
- return 0;
+ return number_of_used_edges;
}
-/**
- \brief Parses command line arguments
- \param argc count of arguments
- \param argv array of arguments
- \param result [out] value for exit return value
- \return true if everything is ok, false if need to terminate execution
-*/
-bool Prepare::ParseArguments(int argc, char *argv[])
+unsigned Prepare::CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list)
{
- // 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", boost::program_options::value<boost::filesystem::path>(&config_file_path)
- ->default_value("contractor.ini"),
- "Path to a configuration file.");
-
- // declare a group of options that will be allowed both on command line and in config file
- boost::program_options::options_description config_options("Configuration");
- config_options.add_options()(
- "restrictions,r",
- boost::program_options::value<boost::filesystem::path>(&restrictions_path),
- "Restrictions file in .osrm.restrictions format")(
- "profile,p", boost::program_options::value<boost::filesystem::path>(&profile_path)
- ->default_value("profile.lua"),
- "Path to LUA routing profile")(
- "threads,t", boost::program_options::value<unsigned int>(&requested_num_threads)
- ->default_value(tbb::task_scheduler_init::default_num_threads()),
- "Number of threads to use");
-
- // hidden options, will be allowed both on command line and in config file, but will not be
- // shown to the user
- boost::program_options::options_description hidden_options("Hidden options");
- hidden_options.add_options()(
- "input,i", boost::program_options::value<boost::filesystem::path>(&input_path),
- "Input file in .osm, .osm.bz2 or .osm.pbf format");
-
- // positional option
- boost::program_options::positional_options_description positional_options;
- positional_options.add("input", 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 config_file_options;
- config_file_options.add(config_options).add(hidden_options);
-
- boost::program_options::options_description visible_options(
- "Usage: " + boost::filesystem::basename(argv[0]) + " <input.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);
-
- const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
- if (boost::filesystem::is_regular_file(temp_config_path))
- {
- boost::program_options::store(boost::program_options::parse_config_file<char>(
- temp_config_path.string().c_str(), cmdline_options, true),
- option_variables);
- }
-
- if (option_variables.count("version"))
- {
- SimpleLogger().Write() << g_GIT_DESCRIPTION;
- return false;
- }
-
- if (option_variables.count("help"))
- {
- SimpleLogger().Write() << "\n" << visible_options;
- return false;
- }
-
- boost::program_options::notify(option_variables);
-
- if (!option_variables.count("restrictions"))
+ RangebasedCRC32 crc32;
+ if (crc32.using_hardware())
{
- restrictions_path = std::string(input_path.string() + ".restrictions");
+ SimpleLogger().Write() << "using hardware based CRC32 computation";
}
-
- if (!option_variables.count("input"))
+ else
{
- SimpleLogger().Write() << "\n" << visible_options;
- return false;
+ SimpleLogger().Write() << "using software based CRC32 computation";
}
- return true;
-}
-
-/**
- \brief Loads and checks file UUIDs
-*/
-void Prepare::CheckRestrictionsFile(FingerPrint &fingerprint_orig)
-{
- boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
- FingerPrint fingerprint_loaded;
- unsigned number_of_usable_restrictions = 0;
- restriction_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
- if (!fingerprint_loaded.TestPrepare(fingerprint_orig))
- {
- SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
- "Reprocess to get rid of this warning.";
- }
+ const unsigned crc32_value = crc32(*node_based_edge_list);
+ SimpleLogger().Write() << "CRC32: " << crc32_value;
- restriction_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
- restriction_list.resize(number_of_usable_restrictions);
- if (number_of_usable_restrictions > 0)
- {
- restriction_stream.read((char *)&(restriction_list[0]),
- number_of_usable_restrictions * sizeof(TurnRestriction));
- }
- restriction_stream.close();
+ return crc32_value;
}
/**
\brief Setups scripting environment (lua-scripting)
Also initializes speed profile.
*/
-bool Prepare::SetupScriptingEnvironment(
+void Prepare::SetupScriptingEnvironment(
lua_State *lua_state, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
{
// open utility libraries string library;
luaL_openlibs(lua_state);
// adjust lua load path
- luaAddScriptFolderToLoadPath(lua_state, profile_path.string().c_str());
+ luaAddScriptFolderToLoadPath(lua_state, config.profile_path.string().c_str());
// Now call our function in a lua script
- if (0 != luaL_dofile(lua_state, profile_path.string().c_str()))
+ if (0 != luaL_dofile(lua_state, config.profile_path.string().c_str()))
{
- std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
- return false;
+ std::stringstream msg;
+ msg << lua_tostring(lua_state, -1) << " occured in scripting block";
+ throw osrm::exception(msg.str());
}
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
{
- std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
- return false;
+ std::stringstream msg;
+ msg << lua_tostring(lua_state, -1) << " occured in scripting block";
+ throw osrm::exception(msg.str());
}
speed_profile.traffic_signal_penalty = 10 * lua_tointeger(lua_state, -1);
SimpleLogger().Write(logDEBUG)
@@ -476,92 +291,140 @@ bool Prepare::SetupScriptingEnvironment(
if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
{
- std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
- return false;
+ std::stringstream msg;
+ msg << lua_tostring(lua_state, -1) << " occured in scripting block";
+ throw osrm::exception(msg.str());
}
speed_profile.u_turn_penalty = 10 * lua_tointeger(lua_state, -1);
speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");
+}
- return true;
+/**
+ \brief Build load restrictions from .restriction file
+ */
+std::shared_ptr<RestrictionMap> Prepare::LoadRestrictionMap()
+{
+ boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary);
+
+ std::vector<TurnRestriction> restriction_list;
+ loadRestrictionsFromFile(input_stream, restriction_list);
+
+ SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions.";
+
+ return std::make_shared<RestrictionMap>(restriction_list);
}
/**
+ \brief Load node based graph from .osrm file
+ */
+std::shared_ptr<NodeBasedDynamicGraph>
+Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
+ std::vector<NodeID> &traffic_light_list,
+ std::vector<QueryNode>& internal_to_external_node_map)
+{
+ std::vector<NodeBasedEdge> edge_list;
+
+ boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary);
+
+ NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream,
+ barrier_node_list, traffic_light_list,
+ internal_to_external_node_map);
+
+ SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, "
+ << traffic_light_list.size() << " traffic lights";
+
+ loadEdgesFromFile(input_stream, edge_list);
+
+ if (edge_list.empty())
+ {
+ SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
+ return std::shared_ptr<NodeBasedDynamicGraph>();
+ }
+
+ return NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
+}
+
+
+/**
\brief Building an edge-expanded graph from node-based input and turn restrictions
*/
-std::size_t
-Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
- NodeID number_of_node_based_nodes,
+std::pair<std::size_t, std::size_t>
+Prepare::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
- DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
- EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
+ DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
{
- SimpleLogger().Write() << "Generating edge-expanded graph representation";
- std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
- NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
- std::unique_ptr<RestrictionMap> restriction_map =
- osrm::make_unique<RestrictionMap>(restriction_list);
- std::shared_ptr<EdgeBasedGraphFactory> edge_based_graph_factory =
- std::make_shared<EdgeBasedGraphFactory>(node_based_graph, std::move(restriction_map),
- barrier_node_list, traffic_light_list,
- internal_to_external_node_map, speed_profile);
- edge_list.clear();
- edge_list.shrink_to_fit();
-
- edge_based_graph_factory->Run(edge_out, geometry_filename, lua_state);
-
- restriction_list.clear();
- restriction_list.shrink_to_fit();
- barrier_node_list.clear();
- barrier_node_list.shrink_to_fit();
- traffic_light_list.clear();
- traffic_light_list.shrink_to_fit();
+ lua_State *lua_state = luaL_newstate();
+ luabind::open(lua_state);
+
+ EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
+
+ SetupScriptingEnvironment(lua_state, speed_profile);
+
+ auto barrier_node_list = osrm::make_unique<std::vector<NodeID>>();
+ auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>();
+
+ auto restriction_map = LoadRestrictionMap();
+ auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map);
+
+ const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
+
+ EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
+ restriction_map,
+ std::move(barrier_node_list),
+ std::move(traffic_light_list),
+ internal_to_external_node_map,
+ speed_profile);
+
+ edge_based_graph_factory.Run(config.edge_output_path, config.geometry_output_path, lua_state);
+ lua_close(lua_state);
const std::size_t number_of_edge_based_nodes =
- edge_based_graph_factory->GetNumberOfEdgeBasedNodes();
+ edge_based_graph_factory.GetNumberOfEdgeBasedNodes();
BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
-#ifndef WIN32
- static_assert(sizeof(EdgeBasedEdge) == 16,
- "changing ImportEdge type has influence on memory consumption!");
-#endif
- edge_based_graph_factory->GetEdgeBasedEdges(edge_based_edge_list);
- edge_based_graph_factory->GetEdgeBasedNodes(node_based_edge_list);
+ edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
+ edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
- edge_based_graph_factory.reset();
- node_based_graph.reset();
+ return std::make_pair(number_of_node_based_nodes, number_of_edge_based_nodes);
+}
- return number_of_edge_based_nodes;
+/**
+ \brief Build contracted graph.
+ */
+void Prepare::ContractGraph(const std::size_t number_of_edge_based_nodes,
+ DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
+ DeallocatingVector<QueryEdge>& contracted_edge_list)
+{
+ Contractor contractor(number_of_edge_based_nodes, edge_based_edge_list);
+ contractor.Run();
+ contractor.GetEdges(contracted_edge_list);
}
/**
\brief Writing info on original (node-based) nodes
*/
-void Prepare::WriteNodeMapping()
+void Prepare::WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map)
{
- SimpleLogger().Write() << "writing node map ...";
- boost::filesystem::ofstream node_stream(node_filename, std::ios::binary);
- const unsigned size_of_mapping = internal_to_external_node_map.size();
+ boost::filesystem::ofstream node_stream(config.node_output_path, std::ios::binary);
+ const unsigned size_of_mapping = internal_to_external_node_map->size();
node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
if (size_of_mapping > 0)
{
- node_stream.write((char *)&(internal_to_external_node_map[0]),
+ node_stream.write((char *) internal_to_external_node_map->data(),
size_of_mapping * sizeof(QueryNode));
}
node_stream.close();
- internal_to_external_node_map.clear();
- internal_to_external_node_map.shrink_to_fit();
}
/**
\brief Building rtree-based nearest-neighbor data structure
- Saves info to files: '.ramIndex' and '.fileIndex'.
+ Saves tree into '.ramIndex' and leaves into '.fileIndex'.
*/
-void Prepare::BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list)
+void Prepare::BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list, const std::vector<QueryNode>& internal_to_external_node_map)
{
- SimpleLogger().Write() << "building r-tree ...";
- StaticRTree<EdgeBasedNode>(node_based_edge_list, rtree_nodes_path.c_str(),
- rtree_leafs_path.c_str(), internal_to_external_node_map);
+ StaticRTree<EdgeBasedNode>(node_based_edge_list, config.rtree_nodes_output_path.c_str(),
+ config.rtree_leafs_output_path.c_str(), internal_to_external_node_map);
}
diff --git a/contractor/processing_chain.hpp b/contractor/processing_chain.hpp
index 933213a..2817681 100644
--- a/contractor/processing_chain.hpp
+++ b/contractor/processing_chain.hpp
@@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PROCESSING_CHAIN_HPP
#define PROCESSING_CHAIN_HPP
+#include "contractor_options.hpp"
#include "edge_based_graph_factory.hpp"
#include "../data_structures/query_edge.hpp"
#include "../data_structures/static_graph.hpp"
-class FingerPrint;
struct EdgeBasedNode;
struct lua_State;
@@ -50,46 +50,36 @@ class Prepare
using InputEdge = DynamicGraph<EdgeData>::InputEdge;
using StaticEdge = StaticGraph<EdgeData>::InputEdge;
- explicit Prepare();
+ explicit Prepare(const ContractorConfig& contractor_config)
+ : config(contractor_config) {}
Prepare(const Prepare &) = delete;
~Prepare();
- int Process(int argc, char *argv[]);
+ int Run();
protected:
- bool ParseArguments(int argc, char *argv[]);
- void CheckRestrictionsFile(FingerPrint &fingerprint_orig);
- bool SetupScriptingEnvironment(lua_State *myLuaState,
+ void SetupScriptingEnvironment(lua_State *myLuaState,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
- std::size_t BuildEdgeExpandedGraph(lua_State *myLuaState,
- NodeID nodeBasedNodeNumber,
- std::vector<EdgeBasedNode> &nodeBasedEdgeList,
- DeallocatingVector<EdgeBasedEdge> &edgeBasedEdgeList,
- EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
- void WriteNodeMapping();
- void BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list);
-
+ std::shared_ptr<RestrictionMap> LoadRestrictionMap();
+ unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list);
+ void ContractGraph(const std::size_t number_of_edge_based_nodes,
+ DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
+ DeallocatingVector<QueryEdge>& contracted_edge_list);
+ std::size_t WriteContractedGraph(unsigned number_of_edge_based_nodes,
+ std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
+ std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list);
+ std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
+ std::vector<NodeID> &traffic_light_list,
+ std::vector<QueryNode>& internal_to_external_node_map);
+ std::pair<std::size_t, std::size_t>
+ BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
+ std::vector<EdgeBasedNode> &node_based_edge_list,
+ DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
+ void WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map);
+ void BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list,
+ const std::vector<QueryNode> &internal_to_external_node_map);
private:
- std::vector<QueryNode> internal_to_external_node_map;
- std::vector<TurnRestriction> restriction_list;
- std::vector<NodeID> barrier_node_list;
- std::vector<NodeID> traffic_light_list;
- std::vector<ImportEdge> edge_list;
-
- unsigned requested_num_threads;
- boost::filesystem::path config_file_path;
- boost::filesystem::path input_path;
- boost::filesystem::path restrictions_path;
- boost::filesystem::path preinfo_path;
- boost::filesystem::path profile_path;
-
- std::string node_filename;
- std::string edge_out;
- std::string info_out;
- std::string geometry_filename;
- std::string graph_out;
- std::string rtree_nodes_path;
- std::string rtree_leafs_path;
+ ContractorConfig config;
};
#endif // PROCESSING_CHAIN_HPP
diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp
index 43e6c3a..b18204c 100644
--- a/data_structures/dynamic_graph.hpp
+++ b/data_structures/dynamic_graph.hpp
@@ -85,6 +85,9 @@ template <typename EdgeDataT> class DynamicGraph
edge_list.resize(number_of_nodes);
}
+ /**
+ * Constructs a DynamicGraph from a list of edges sorted by source node id.
+ */
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
{
number_of_nodes = nodes;
diff --git a/data_structures/import_edge.cpp b/data_structures/import_edge.cpp
index f41b066..3f2146c 100644
--- a/data_structures/import_edge.cpp
+++ b/data_structures/import_edge.cpp
@@ -47,6 +47,13 @@ bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
return source < other.source;
}
+NodeBasedEdge::NodeBasedEdge()
+ : source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
+ backward(false), roundabout(false), in_tiny_cc(false),
+ access_restricted(false), is_split(false), travel_mode(false)
+{
+}
+
NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
diff --git a/data_structures/import_edge.hpp b/data_structures/import_edge.hpp
index f422de1..e489850 100644
--- a/data_structures/import_edge.hpp
+++ b/data_structures/import_edge.hpp
@@ -35,6 +35,7 @@ struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
+ NodeBasedEdge();
explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
@@ -58,8 +59,6 @@ struct NodeBasedEdge
bool access_restricted : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
-
- NodeBasedEdge() = delete;
};
struct EdgeBasedEdge
@@ -86,6 +85,4 @@ struct EdgeBasedEdge
bool backward : 1;
};
-using ImportEdge = NodeBasedEdge;
-
#endif /* IMPORT_EDGE_HPP */
diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp
index 54e07a7..b69053a 100644
--- a/data_structures/node_based_graph.hpp
+++ b/data_structures/node_based_graph.hpp
@@ -64,7 +64,7 @@ struct NodeBasedEdgeData
backward = temp_flag;
}
- bool IsEqualTo(const NodeBasedEdgeData &other) const
+ bool IsCompatibleTo(const NodeBasedEdgeData &other) const
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
@@ -72,26 +72,123 @@ struct NodeBasedEdgeData
}
};
-struct SimpleEdgeData
+using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
+
+inline bool validateNeighborHood(const NodeBasedDynamicGraph& graph, const NodeID source)
{
- SimpleEdgeData() : capacity(0) {}
- EdgeWeight capacity;
-};
+ for (auto edge = graph.BeginEdges(source); edge < graph.EndEdges(source); ++edge)
+ {
+ const auto& data = graph.GetEdgeData(edge);
+ if (!data.forward && !data.backward)
+ {
+ SimpleLogger().Write(logWARNING) << "Invalid edge directions";
+ return false;
+ }
-using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
-using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
+ auto target = graph.GetTarget(edge);
+ if (target == SPECIAL_NODEID)
+ {
+ SimpleLogger().Write(logWARNING) << "Invalid edge target";
+ return false;
+ }
+
+ bool found_reverse = false;
+ for (auto rev_edge = graph.BeginEdges(target); rev_edge < graph.EndEdges(target); ++rev_edge)
+ {
+ auto rev_target = graph.GetTarget(rev_edge);
+ if (rev_target == SPECIAL_NODEID)
+ {
+ SimpleLogger().Write(logWARNING) << "Invalid reverse edge target";
+ return false;
+ }
+
+ if (rev_target != source)
+ {
+ continue;
+ }
+
+ if (found_reverse)
+ {
+ SimpleLogger().Write(logWARNING) << "Found more than one reverse edge";
+ return false;
+ }
+
+ const auto& rev_data = graph.GetEdgeData(rev_edge);
+
+ // edge is incoming, this must be an outgoing edge
+ if (data.backward && !rev_data.forward)
+ {
+ SimpleLogger().Write(logWARNING) << "Found no outgoing edge to an incoming edge!";
+ return false;
+ }
+
+ // edge is bi-directional, reverse must be as well
+ if (data.forward && data.backward && (!rev_data.forward || !rev_data.backward))
+ {
+ SimpleLogger().Write(logWARNING) << "Found bi-directional edge that is not bi-directional to both ends";
+ return false;
+ }
+
+ found_reverse = true;
+
+ }
+
+ if (!found_reverse)
+ {
+ SimpleLogger().Write(logWARNING) << "Could not find reverse edge";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// This function checks if the overal graph is undirected (has an edge in each direction).
+inline bool validateNodeBasedGraph(const NodeBasedDynamicGraph& graph)
+{
+ for (auto source = 0u; source < graph.GetNumberOfNodes(); ++source)
+ {
+ if (!validateNeighborHood(graph, source))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
-// Factory method to create NodeBasedDynamicGraph from ImportEdges
+// Factory method to create NodeBasedDynamicGraph from NodeBasedEdges
+// The since DynamicGraph expects directed edges, we need to insert
+// two edges for undirected edges.
inline std::shared_ptr<NodeBasedDynamicGraph>
-NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
+NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<NodeBasedEdge> &input_edge_list)
{
static_assert(sizeof(NodeBasedEdgeData) == 16,
"changing node based edge data size changes memory consumption");
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
- for (const ImportEdge &import_edge : input_edge_list)
+
+ // Since DynamicGraph assumes directed edges we have to make sure we transformed
+ // the compressed edge format into single directed edges. We do this to make sure
+ // every node also knows its incoming edges, not only its outgoing edges and use the backward=true
+ // flag to indicate which is which.
+ //
+ // We do the transformation in the following way:
+ //
+ // if the edge (a, b) is split:
+ // 1. this edge must be in only one direction, so its a --> b
+ // 2. there must be another directed edge b --> a somewhere in the data
+ // if the edge (a, b) is not split:
+ // 1. this edge be on of a --> b od a <-> b
+ // (a <-- b gets reducted to b --> a)
+ // 2. a --> b will be transformed to a --> b and b <-- a
+ // 3. a <-> b will be transformed to a <-> b and b <-> a (I think a --> b and b <-- a would work as well though)
+ for (const NodeBasedEdge &import_edge : input_edge_list)
{
+ // edges that are not forward get converted by flipping the end points
+ BOOST_ASSERT(import_edge.forward);
+
if (import_edge.forward)
{
edge.source = import_edge.source;
@@ -99,20 +196,10 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
edge.data.forward = import_edge.forward;
edge.data.backward = import_edge.backward;
}
- else
- {
- edge.source = import_edge.target;
- edge.target = import_edge.source;
- edge.data.backward = import_edge.forward;
- edge.data.forward = import_edge.backward;
- }
- if (edge.source == edge.target)
- {
- continue;
- }
+ BOOST_ASSERT(edge.source != edge.target);
- edge.data.distance = (std::max)(static_cast<int>(import_edge.weight), 1);
+ edge.data.distance = static_cast<int>(import_edge.weight);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
edge.data.roundabout = import_edge.roundabout;
@@ -132,147 +219,16 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
}
}
- // remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
- NodeID edge_count = 0;
- for (NodeID i = 0; i < edges_list.size();)
- {
- const NodeID source = edges_list[i].source;
- const NodeID target = edges_list[i].target;
- // remove eigenloops
- if (source == target)
- {
- i++;
- continue;
- }
- NodeBasedDynamicGraph::InputEdge forward_edge;
- NodeBasedDynamicGraph::InputEdge reverse_edge;
- forward_edge = reverse_edge = edges_list[i];
- forward_edge.data.forward = reverse_edge.data.backward = true;
- forward_edge.data.backward = reverse_edge.data.forward = false;
- forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
- forward_edge.data.distance = reverse_edge.data.distance = std::numeric_limits<int>::max();
- // remove parallel edges
- while (i < edges_list.size() && edges_list[i].source == source &&
- edges_list[i].target == target)
- {
- if (edges_list[i].data.forward)
- {
- forward_edge.data.distance =
- std::min(edges_list[i].data.distance, forward_edge.data.distance);
- }
- if (edges_list[i].data.backward)
- {
- reverse_edge.data.distance =
- std::min(edges_list[i].data.distance, reverse_edge.data.distance);
- }
- ++i;
- }
- // merge edges (s,t) and (t,s) into bidirectional edge
- if (forward_edge.data.distance == reverse_edge.data.distance)
- {
- if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
- {
- forward_edge.data.backward = true;
- edges_list[edge_count++] = forward_edge;
- }
- }
- else
- { // insert seperate edges
- if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
- {
- edges_list[edge_count++] = forward_edge;
- }
- if (static_cast<int>(reverse_edge.data.distance) != std::numeric_limits<int>::max())
- {
- edges_list[edge_count++] = reverse_edge;
- }
- }
- }
- edges_list.resize(edge_count);
- SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
- << edges_list.size();
auto graph = std::make_shared<NodeBasedDynamicGraph>(
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
- return graph;
-}
-
-template <class SimpleEdgeT>
-inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
-SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
-{
- static_assert(sizeof(NodeBasedEdgeData) == 16,
- "changing node based edge data size changes memory consumption");
- tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
- DeallocatingVector<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
- SimpleNodeBasedDynamicGraph::InputEdge edge;
- edge.data.capacity = 1;
- for (const SimpleEdgeT &import_edge : input_edge_list)
- {
- if (import_edge.source == import_edge.target)
- {
- continue;
- }
- edge.source = import_edge.source;
- edge.target = import_edge.target;
- edges_list.push_back(edge);
- std::swap(edge.source, edge.target);
- edges_list.push_back(edge);
- }
- // remove duplicate edges
- tbb::parallel_sort(edges_list.begin(), edges_list.end());
- NodeID edge_count = 0;
- for (NodeID i = 0; i < edges_list.size();)
- {
- const NodeID source = edges_list[i].source;
- const NodeID target = edges_list[i].target;
- // remove eigenloops
- if (source == target)
- {
- i++;
- continue;
- }
- SimpleNodeBasedDynamicGraph::InputEdge forward_edge;
- SimpleNodeBasedDynamicGraph::InputEdge reverse_edge;
- forward_edge = reverse_edge = edges_list[i];
- forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
- // remove parallel edges
- while (i < edges_list.size() && edges_list[i].source == source &&
- edges_list[i].target == target)
- {
- forward_edge.data.capacity =
- std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
- reverse_edge.data.capacity =
- std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
- ++i;
- }
- // merge edges (s,t) and (t,s) into bidirectional edge
- if (forward_edge.data.capacity == reverse_edge.data.capacity)
- {
- if (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
- {
- edges_list[edge_count++] = forward_edge;
- }
- }
- else
- { // insert seperate edges
- if (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
- {
- edges_list[edge_count++] = forward_edge;
- }
- if (static_cast<int>(reverse_edge.data.capacity) != INVALID_EDGE_WEIGHT)
- {
- edges_list[edge_count++] = reverse_edge;
- }
- }
- }
- SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
- << edges_list.size();
+#ifndef NDEBUG
+ BOOST_ASSERT(validateNodeBasedGraph(*graph));
+#endif
- auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
return graph;
}
diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp
index 27a6698..98b360c 100644
--- a/data_structures/restriction_map.hpp
+++ b/data_structures/restriction_map.hpp
@@ -91,6 +91,7 @@ template <> struct hash<RestrictionTarget>
class RestrictionMap
{
public:
+ RestrictionMap() : m_count(0) {};
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
// Replace end v with w in each turn restriction containing u as via node
@@ -98,7 +99,7 @@ class RestrictionMap
void FixupArrivingTurnRestriction(const NodeID node_u,
const NodeID node_v,
const NodeID node_w,
- const std::shared_ptr<GraphT> &graph)
+ const GraphT &graph)
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
@@ -112,9 +113,9 @@ class RestrictionMap
// find all potential start edges. It is more efficent to get a (small) list
// of potential start edges than iterating over all buckets
std::vector<NodeID> predecessors;
- for (const EdgeID current_edge_id : graph->GetAdjacentEdgeRange(node_u))
+ for (const EdgeID current_edge_id : graph.GetAdjacentEdgeRange(node_u))
{
- const NodeID target = graph->GetTarget(current_edge_id);
+ const NodeID target = graph.GetTarget(current_edge_id);
if (node_v != target)
{
predecessors.push_back(target);
diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp
index 3b615e2..86b9553 100644
--- a/data_structures/route_parameters.cpp
+++ b/data_structures/route_parameters.cpp
@@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/route_parameters.hpp>
+#include "../algorithms/polyline_compressor.hpp"
+
RouteParameters::RouteParameters()
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
compression(true), deprecatedAPI(false), uturn_default(false), classify(false),
@@ -131,3 +133,9 @@ void RouteParameters::addCoordinate(
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)),
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates)));
}
+
+void RouteParameters::getCoordinatesFromGeometry(const std::string geometry_string)
+{
+ PolylineCompressor pc;
+ coordinates = pc.decode_string(geometry_string);
+}
diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp
index f219a64..fa56071 100644
--- a/data_structures/static_rtree.hpp
+++ b/data_structures/static_rtree.hpp
@@ -344,7 +344,7 @@ class StaticRTree
StaticRTree(const StaticRTree &) = delete;
// Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
- explicit StaticRTree(std::vector<EdgeDataT> &input_data_vector,
+ explicit StaticRTree(const std::vector<EdgeDataT> &input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename,
const std::vector<QueryNode> &coordinate_list)
@@ -646,22 +646,16 @@ class StaticRTree
const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &result_phantom_node_vector,
const unsigned max_number_of_phantom_nodes,
- const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE)
+ const float max_distance = 1100)
{
unsigned inspected_elements = 0;
unsigned number_of_elements_from_big_cc = 0;
unsigned number_of_elements_from_tiny_cc = 0;
-#ifdef NDEBUG
- unsigned pruned_elements = 0;
-#endif
std::pair<double, double> projected_coordinate = {
mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
input_coordinate.lon / COORDINATE_PRECISION};
- // upper bound pruning technique
- upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
-
// initialize queue with root element
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
traversal_queue.emplace(0.f, m_search_tree[0]);
@@ -669,6 +663,10 @@ class StaticRTree
while (!traversal_queue.empty())
{
const IncrementalQueryCandidate current_query_node = traversal_queue.top();
+ if (current_query_node.min_dist > max_distance)
+ {
+ break;
+ }
traversal_queue.pop();
if (current_query_node.node.template is<TreeNode>())
@@ -692,18 +690,7 @@ class StaticRTree
// distance must be non-negative
BOOST_ASSERT(0.f <= current_perpendicular_distance);
- if (pruning_bound.get() >= current_perpendicular_distance ||
- current_edge.is_in_tiny_cc())
- {
- pruning_bound.insert(current_perpendicular_distance);
- traversal_queue.emplace(current_perpendicular_distance, current_edge);
- }
-#ifdef NDEBUG
- else
- {
- ++pruned_elements;
- }
-#endif
+ traversal_queue.emplace(current_perpendicular_distance, current_edge);
}
}
else
@@ -771,9 +758,8 @@ class StaticRTree
}
// stop the search by flushing the queue
- if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
- number_of_elements_from_big_cc > 0) ||
- inspected_elements >= max_checked_elements)
+ if (result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
+ number_of_elements_from_big_cc > 0)
{
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
}
@@ -809,6 +795,10 @@ class StaticRTree
unsigned number_of_elements_from_big_cc = 0;
unsigned number_of_elements_from_tiny_cc = 0;
+ // is true if a big cc was added to the queue to we also have a lower bound
+ // for them. it actives pruning for big components
+ bool has_big_cc = false;
+
unsigned pruned_elements = 0;
std::pair<double, double> projected_coordinate = {
@@ -849,10 +839,11 @@ class StaticRTree
BOOST_ASSERT(0.f <= current_perpendicular_distance);
if (pruning_bound.get() >= current_perpendicular_distance ||
- current_edge.is_in_tiny_cc())
+ (!has_big_cc && !current_edge.is_in_tiny_cc()))
{
pruning_bound.insert(current_perpendicular_distance);
traversal_queue.emplace(current_perpendicular_distance, current_edge);
+ has_big_cc = has_big_cc || !current_edge.is_in_tiny_cc();
}
else
{
diff --git a/datastore.cpp b/datastore.cpp
index 3c032a2..89efefc 100644
--- a/datastore.cpp
+++ b/datastore.cpp
@@ -264,9 +264,10 @@ int main(const int argc, const char *argv[])
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
- FingerPrint fingerprint_loaded, fingerprint_orig;
+ FingerPrint fingerprint_valid = FingerPrint::GetValid();
+ FingerPrint fingerprint_loaded;
hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
- if (fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+ if (fingerprint_loaded.TestGraphUtil(fingerprint_valid))
{
SimpleLogger().Write(logDEBUG) << "Fingerprint checked out ok";
}
diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp
index e466562..71dd795 100644
--- a/descriptors/description_factory.cpp
+++ b/descriptors/description_factory.cpp
@@ -173,6 +173,7 @@ void DescriptionFactory::Run(const unsigned zoom_level)
// }
// string0 = string1;
// }
+ //
float segment_length = 0.;
EdgeWeight segment_duration = 0;
@@ -197,7 +198,8 @@ void DescriptionFactory::Run(const unsigned zoom_level)
// Post-processing to remove empty or nearly empty path segments
if (path_description.size() > 2 &&
- std::numeric_limits<float>::epsilon() > path_description.back().length)
+ std::numeric_limits<float>::epsilon() > path_description.back().length &&
+ !(path_description.end() - 2)->is_via_location)
{
path_description.pop_back();
path_description.back().necessary = true;
@@ -206,7 +208,8 @@ void DescriptionFactory::Run(const unsigned zoom_level)
}
if (path_description.size() > 2 &&
- std::numeric_limits<float>::epsilon() > path_description.front().length)
+ std::numeric_limits<float>::epsilon() > path_description.front().length &&
+ !(path_description.begin() + 1)->is_via_location)
{
path_description.erase(path_description.begin());
path_description.front().turn_instruction = TurnInstruction::HeadOn;
diff --git a/extract.cpp b/extract.cpp
index a147629..5f88cc3 100644
--- a/extract.cpp
+++ b/extract.cpp
@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
<< " not found!";
return 1;
}
- return extractor().run(extractor_config);
+ return extractor(extractor_config).run();
}
catch (const std::exception &e)
{
diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp
index 7c912f3..caca05c 100644
--- a/extractor/extraction_containers.cpp
+++ b/extractor/extraction_containers.cpp
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../util/osrm_exception.hpp"
#include "../util/simple_logger.hpp"
#include "../util/timing_util.hpp"
+#include "../util/fingerprint.hpp"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -54,6 +55,7 @@ ExtractionContainers::ExtractionContainers()
ExtractionContainers::~ExtractionContainers()
{
+ // FIXME isn't this done implicitly of the stxxl::vectors go out of scope?
used_node_id_list.clear();
all_nodes_list.clear();
all_edges_list.clear();
@@ -71,394 +73,561 @@ ExtractionContainers::~ExtractionContainers()
* - filter nodes list to nodes that are referenced by ways
* - merge edges with nodes to include location of start/end points and serialize
*
- * FIXME: Each of this step should be an own function for readability.
*/
void ExtractionContainers::PrepareData(const std::string &output_file_name,
- const std::string &restrictions_file_name)
+ const std::string &restrictions_file_name,
+ const std::string &name_file_name)
{
try
{
- unsigned number_of_used_nodes = 0;
- unsigned number_of_used_edges = 0;
-
- std::cout << "[extractor] Sorting used nodes ... " << std::flush;
- TIMER_START(sorting_used_nodes);
- stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
- TIMER_STOP(sorting_used_nodes);
- std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
-
- std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
- TIMER_START(erasing_dups);
- auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
- used_node_id_list.resize(new_end - used_node_id_list.begin());
- TIMER_STOP(erasing_dups);
- std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
-
- std::cout << "[extractor] Sorting all nodes ... " << std::flush;
- TIMER_START(sorting_nodes);
- stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(),
- stxxl_memory);
- TIMER_STOP(sorting_nodes);
- std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
-
- std::cout << "[extractor] Sorting used ways ... " << std::flush;
- TIMER_START(sort_ways);
- stxxl::sort(way_start_end_id_list.begin(), way_start_end_id_list.end(),
- FirstAndLastSegmentOfWayStxxlCompare(), stxxl_memory);
- TIMER_STOP(sort_ways);
- std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
-
- std::cout << "[extractor] Sorting " << restrictions_list.size()
- << " restrictions. by from... " << std::flush;
- TIMER_START(sort_restrictions);
- stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
- CmpRestrictionContainerByFrom(), stxxl_memory);
- TIMER_STOP(sort_restrictions);
- std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
-
- std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
- TIMER_START(fix_restriction_starts);
- auto restrictions_iterator = restrictions_list.begin();
- auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
-
- while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
- restrictions_iterator != restrictions_list.end())
+ std::ofstream file_out_stream;
+ file_out_stream.open(output_file_name.c_str(), std::ios::binary);
+ const FingerPrint fingerprint = FingerPrint::GetValid();
+ file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
+
+ PrepareNodes();
+ WriteNodes(file_out_stream);
+ PrepareEdges();
+ WriteEdges(file_out_stream);
+
+ file_out_stream.close();
+
+ PrepareRestrictions();
+ WriteRestrictions(restrictions_file_name);
+
+ WriteNames(name_file_name);
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Caught Execption:" << e.what() << std::endl;
+ }
+}
+
+void ExtractionContainers::WriteNames(const std::string& names_file_name) const
+{
+ std::cout << "[extractor] writing street name index ... " << std::flush;
+ TIMER_START(write_name_index);
+ boost::filesystem::ofstream name_file_stream(names_file_name, std::ios::binary);
+
+ unsigned total_length = 0;
+ std::vector<unsigned> name_lengths;
+ for (const std::string &temp_string : name_list)
+ {
+ const unsigned string_length =
+ std::min(static_cast<unsigned>(temp_string.length()), 255u);
+ name_lengths.push_back(string_length);
+ total_length += string_length;
+ }
+
+ // builds and writes the index
+ RangeTable<> name_index_range(name_lengths);
+ name_file_stream << name_index_range;
+
+ name_file_stream.write((char *)&total_length, sizeof(unsigned));
+ // write all chars consecutively
+ for (const std::string &temp_string : name_list)
+ {
+ const unsigned string_length =
+ std::min(static_cast<unsigned>(temp_string.length()), 255u);
+ name_file_stream.write(temp_string.c_str(), string_length);
+ }
+
+ name_file_stream.close();
+ TIMER_STOP(write_name_index);
+ std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
+}
+
+void ExtractionContainers::PrepareNodes()
+{
+ std::cout << "[extractor] Sorting used nodes ... " << std::flush;
+ TIMER_START(sorting_used_nodes);
+ stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
+ TIMER_STOP(sorting_used_nodes);
+ std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
+
+ std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
+ TIMER_START(erasing_dups);
+ auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
+ used_node_id_list.resize(new_end - used_node_id_list.begin());
+ TIMER_STOP(erasing_dups);
+ std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
+
+ std::cout << "[extractor] Building node id map ... " << std::flush;
+ TIMER_START(id_map);
+ external_to_internal_node_id_map.reserve(used_node_id_list.size());
+ for (NodeID i = 0u; i < used_node_id_list.size(); ++i)
+ external_to_internal_node_id_map[used_node_id_list[i]] = i;
+ TIMER_STOP(id_map);
+ std::cout << "ok, after " << TIMER_SEC(id_map) << "s" << std::endl;
+
+ std::cout << "[extractor] Sorting all nodes ... " << std::flush;
+ TIMER_START(sorting_nodes);
+ stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(),
+ stxxl_memory);
+ TIMER_STOP(sorting_nodes);
+ std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
+}
+
+void ExtractionContainers::PrepareEdges()
+{
+ // Sort edges by start.
+ std::cout << "[extractor] Sorting edges by start ... " << std::flush;
+ TIMER_START(sort_edges_by_start);
+ stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
+ TIMER_STOP(sort_edges_by_start);
+ std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
+
+ std::cout << "[extractor] Setting start coords ... " << std::flush;
+ TIMER_START(set_start_coords);
+ // Traverse list of edges and nodes in parallel and set start coord
+ auto node_iterator = all_nodes_list.begin();
+ auto edge_iterator = all_edges_list.begin();
+ while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+ {
+ if (edge_iterator->result.source < node_iterator->node_id)
{
- if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
- {
- ++way_start_and_end_iterator;
- continue;
- }
+ edge_iterator->result.source = SPECIAL_NODEID;
+ ++edge_iterator;
+ continue;
+ }
+ if (edge_iterator->result.source > node_iterator->node_id)
+ {
+ node_iterator++;
+ continue;
+ }
- if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
- {
- ++restrictions_iterator;
- continue;
- }
+ // remove loops
+ if (edge_iterator->result.source == edge_iterator->result.target)
+ {
+ edge_iterator->result.source = SPECIAL_NODEID;
+ edge_iterator->result.target = SPECIAL_NODEID;
+ ++edge_iterator;
+ continue;
+ }
- BOOST_ASSERT(way_start_and_end_iterator->way_id ==
- restrictions_iterator->restriction.from.way);
- const NodeID via_node_id = restrictions_iterator->restriction.via.node;
+ BOOST_ASSERT(edge_iterator->result.source == node_iterator->node_id);
- if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
- {
- restrictions_iterator->restriction.from.node =
- way_start_and_end_iterator->first_segment_target_id;
- }
- else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
- {
- restrictions_iterator->restriction.from.node =
- way_start_and_end_iterator->last_segment_source_id;
- }
- ++restrictions_iterator;
+ // assign new node id
+ auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
+ BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
+ edge_iterator->result.source = id_iter->second;
+
+ edge_iterator->source_coordinate.lat = node_iterator->lat;
+ edge_iterator->source_coordinate.lon = node_iterator->lon;
+ ++edge_iterator;
+ }
+ TIMER_STOP(set_start_coords);
+ std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
+
+ // Sort Edges by target
+ std::cout << "[extractor] Sorting edges by target ... " << std::flush;
+ TIMER_START(sort_edges_by_target);
+ stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(),
+ stxxl_memory);
+ TIMER_STOP(sort_edges_by_target);
+ std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
+
+ // Compute edge weights
+ std::cout << "[extractor] Computing edge weights ... " << std::flush;
+ TIMER_START(compute_weights);
+ node_iterator = all_nodes_list.begin();
+ edge_iterator = all_edges_list.begin();
+ while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+ {
+ // skip all invalid edges
+ if (edge_iterator->result.source == SPECIAL_NODEID)
+ {
+ ++edge_iterator;
+ continue;
}
- TIMER_STOP(fix_restriction_starts);
- std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
-
- std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
- TIMER_START(sort_restrictions_to);
- stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
- CmpRestrictionContainerByTo(), stxxl_memory);
- TIMER_STOP(sort_restrictions_to);
- std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
-
- std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
- TIMER_START(fix_restriction_ends);
- restrictions_iterator = restrictions_list.begin();
- way_start_and_end_iterator = way_start_end_id_list.cbegin();
- while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
- restrictions_iterator != restrictions_list.end())
+ if (edge_iterator->result.target < node_iterator->node_id)
{
- if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
- {
- ++way_start_and_end_iterator;
- continue;
- }
- if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
- {
- ++restrictions_iterator;
- continue;
- }
- BOOST_ASSERT(way_start_and_end_iterator->way_id ==
- restrictions_iterator->restriction.to.way);
- const NodeID via_node_id = restrictions_iterator->restriction.via.node;
+ edge_iterator->result.target = SPECIAL_NODEID;
+ ++edge_iterator;
+ continue;
+ }
+ if (edge_iterator->result.target > node_iterator->node_id)
+ {
+ ++node_iterator;
+ continue;
+ }
- if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
- {
- restrictions_iterator->restriction.to.node =
- way_start_and_end_iterator->first_segment_target_id;
- }
- else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
+ BOOST_ASSERT(edge_iterator->result.target == node_iterator->node_id);
+ BOOST_ASSERT(edge_iterator->weight_data.speed >= 0);
+ BOOST_ASSERT(edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min());
+ BOOST_ASSERT(edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min());
+
+ const double distance = coordinate_calculation::euclidean_distance(
+ edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
+ node_iterator->lat, node_iterator->lon);
+
+ const double weight = [distance](const InternalExtractorEdge::WeightData& data) {
+ switch (data.type)
{
- restrictions_iterator->restriction.to.node =
- way_start_and_end_iterator->last_segment_source_id;
+ case InternalExtractorEdge::WeightType::EDGE_DURATION:
+ case InternalExtractorEdge::WeightType::WAY_DURATION:
+ return data.duration * 10.;
+ break;
+ case InternalExtractorEdge::WeightType::SPEED:
+ return (distance * 10.) / (data.speed / 3.6);
+ break;
+ case InternalExtractorEdge::WeightType::INVALID:
+ osrm::exception("invalid weight type");
}
- ++restrictions_iterator;
+ return -1.0;
+ }(edge_iterator->weight_data);
+
+ auto& edge = edge_iterator->result;
+ edge.weight = std::max(1, static_cast<int>(std::floor(weight + .5)));
+
+ // assign new node id
+ auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
+ BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
+ edge.target = id_iter->second;
+
+ // orient edges consistently: source id < target id
+ // important for multi-edge removal
+ if (edge.source > edge.target)
+ {
+ std::swap(edge.source, edge.target);
+
+ // std::swap does not work with bit-fields
+ bool temp = edge.forward;
+ edge.forward = edge.backward;
+ edge.backward = temp;
}
- TIMER_STOP(fix_restriction_ends);
- std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
-
- // serialize restrictions
- std::ofstream restrictions_out_stream;
- unsigned written_restriction_count = 0;
- restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
- restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
- const auto count_position = restrictions_out_stream.tellp();
- restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
-
- for (const auto &restriction_container : restrictions_list)
+ ++edge_iterator;
+ }
+ TIMER_STOP(compute_weights);
+ std::cout << "ok, after " << TIMER_SEC(compute_weights) << "s" << std::endl;
+
+ // Sort edges by start.
+ std::cout << "[extractor] Sorting edges by renumbered start ... " << std::flush;
+ TIMER_START(sort_edges_by_renumbered_start);
+ stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartThenTargetID(), stxxl_memory);
+ TIMER_STOP(sort_edges_by_renumbered_start);
+ std::cout << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s" << std::endl;
+
+ BOOST_ASSERT(all_edges_list.size() > 0);
+ for (unsigned i = 0; i < all_edges_list.size();)
+ {
+ // only invalid edges left
+ if (all_edges_list[i].result.source == SPECIAL_NODEID)
{
- if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
- SPECIAL_NODEID != restriction_container.restriction.to.node)
- {
- restrictions_out_stream.write((char *)&(restriction_container.restriction),
- sizeof(TurnRestriction));
- ++written_restriction_count;
- }
+ break;
+ }
+ // skip invalid edges
+ if (all_edges_list[i].result.target == SPECIAL_NODEID)
+ {
+ continue;
}
- restrictions_out_stream.seekp(count_position);
- restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
- restrictions_out_stream.close();
- SimpleLogger().Write() << "usable restrictions: " << written_restriction_count;
+ unsigned start_idx = i;
+ NodeID source = all_edges_list[i].result.source;
+ NodeID target = all_edges_list[i].result.target;
- std::ofstream file_out_stream;
- file_out_stream.open(output_file_name.c_str(), std::ios::binary);
- file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
- file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
- std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
- TIMER_START(write_nodes);
- // identify all used nodes by a merging step of two sorted lists
- auto node_iterator = all_nodes_list.begin();
- auto node_id_iterator = used_node_id_list.begin();
- while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
+ int min_forward_weight = std::numeric_limits<int>::max();
+ int min_backward_weight = std::numeric_limits<int>::max();
+ unsigned min_forward_idx = std::numeric_limits<unsigned>::max();
+ unsigned min_backward_idx = std::numeric_limits<unsigned>::max();
+
+ // find minimal edge in both directions
+ while (all_edges_list[i].result.source == source &&
+ all_edges_list[i].result.target == target)
{
- if (*node_id_iterator < node_iterator->node_id)
+ if (all_edges_list[i].result.forward && all_edges_list[i].result.weight < min_forward_weight)
{
- ++node_id_iterator;
- continue;
+ min_forward_idx = i;
}
- if (*node_id_iterator > node_iterator->node_id)
+ if (all_edges_list[i].result.backward && all_edges_list[i].result.weight < min_backward_weight)
{
- ++node_iterator;
- continue;
+ min_backward_idx = i;
}
- BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
- file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
-
- ++number_of_used_nodes;
- ++node_id_iterator;
- ++node_iterator;
+ // this also increments the outer loop counter!
+ i++;
}
- TIMER_STOP(write_nodes);
- std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
-
- std::cout << "[extractor] setting number of nodes ... " << std::flush;
- std::ios::pos_type previous_file_position = file_out_stream.tellp();
- file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
- file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
- file_out_stream.seekp(previous_file_position);
-
- std::cout << "ok" << std::endl;
-
- // Sort edges by start.
- std::cout << "[extractor] Sorting edges by start ... " << std::flush;
- TIMER_START(sort_edges_by_start);
- stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
- TIMER_STOP(sort_edges_by_start);
- std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
-
- std::cout << "[extractor] Setting start coords ... " << std::flush;
- TIMER_START(set_start_coords);
- file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
- // Traverse list of edges and nodes in parallel and set start coord
- node_iterator = all_nodes_list.begin();
- auto edge_iterator = all_edges_list.begin();
- while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+ BOOST_ASSERT(min_forward_idx == std::numeric_limits<unsigned>::max() || min_forward_idx < i);
+ BOOST_ASSERT(min_backward_idx == std::numeric_limits<unsigned>::max() || min_backward_idx < i);
+ BOOST_ASSERT(min_backward_idx != std::numeric_limits<unsigned>::max() ||
+ min_forward_idx != std::numeric_limits<unsigned>::max());
+
+ if (min_backward_idx == min_forward_idx)
+ {
+ all_edges_list[min_forward_idx].result.is_split = false;
+ all_edges_list[min_forward_idx].result.forward = true;
+ all_edges_list[min_forward_idx].result.backward = true;
+ }
+ else
{
- if (edge_iterator->start < node_iterator->node_id)
+ bool has_forward = min_forward_idx != std::numeric_limits<unsigned>::max();
+ bool has_backward = min_backward_idx != std::numeric_limits<unsigned>::max();
+ if (has_forward)
{
- ++edge_iterator;
- continue;
+ all_edges_list[min_forward_idx].result.forward = true;
+ all_edges_list[min_forward_idx].result.backward = false;
+ all_edges_list[min_forward_idx].result.is_split = has_backward;
}
- if (edge_iterator->start > node_iterator->node_id)
+ if (has_backward)
{
- node_iterator++;
- continue;
+ std::swap(all_edges_list[min_backward_idx].result.source,
+ all_edges_list[min_backward_idx].result.target);
+ all_edges_list[min_backward_idx].result.forward = true;
+ all_edges_list[min_backward_idx].result.backward = false;
+ all_edges_list[min_backward_idx].result.is_split = has_forward;
}
-
- BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
- edge_iterator->source_coordinate.lat = node_iterator->lat;
- edge_iterator->source_coordinate.lon = node_iterator->lon;
- ++edge_iterator;
}
- TIMER_STOP(set_start_coords);
- std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
-
- // Sort Edges by target
- std::cout << "[extractor] Sorting edges by target ... " << std::flush;
- TIMER_START(sort_edges_by_target);
- stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(),
- stxxl_memory);
- TIMER_STOP(sort_edges_by_target);
- std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
-
- std::cout << "[extractor] Setting target coords ... " << std::flush;
- TIMER_START(set_target_coords);
- // Traverse list of edges and nodes in parallel and set target coord
- node_iterator = all_nodes_list.begin();
- edge_iterator = all_edges_list.begin();
-
- // Also serializes the edges
- while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
+
+ // invalidate all unused edges
+ for (unsigned j = start_idx; j < i; j++)
{
- if (edge_iterator->target < node_iterator->node_id)
- {
- ++edge_iterator;
- continue;
- }
- if (edge_iterator->target > node_iterator->node_id)
+ if (j == min_forward_idx || j == min_backward_idx)
{
- ++node_iterator;
continue;
}
- BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
- if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
- edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
- {
- BOOST_ASSERT(edge_iterator->speed != -1);
- edge_iterator->target_coordinate.lat = node_iterator->lat;
- edge_iterator->target_coordinate.lon = node_iterator->lon;
-
- const double distance = coordinate_calculation::euclidean_distance(
- edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
- node_iterator->lat, node_iterator->lon);
-
- const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
- int integer_weight = std::max(
- 1, (int)std::floor(
- (edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
- // FIXME: This means we have a _minimum_ edge length of 1m
- // maybe use dm as base unit?
- const int integer_distance = std::max(1, (int)distance);
- const short zero = 0;
- const short one = 1;
- const bool yes = true;
- const bool no = false;
-
- file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
- file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
- file_out_stream.write((char *)&integer_distance, sizeof(int));
- switch (edge_iterator->direction)
- {
- case ExtractionWay::notSure:
- file_out_stream.write((char *)&zero, sizeof(short));
- break;
- case ExtractionWay::oneway:
- file_out_stream.write((char *)&one, sizeof(short));
- break;
- case ExtractionWay::bidirectional:
- file_out_stream.write((char *)&zero, sizeof(short));
- break;
- case ExtractionWay::opposite:
- file_out_stream.write((char *)&one, sizeof(short));
- break;
- default:
- throw osrm::exception("edge has broken direction");
- }
-
- file_out_stream.write((char *)&integer_weight, sizeof(int));
- file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
- if (edge_iterator->is_roundabout)
- {
- file_out_stream.write((char *)&yes, sizeof(bool));
- }
- else
- {
- file_out_stream.write((char *)&no, sizeof(bool));
- }
- if (edge_iterator->is_in_tiny_cc)
- {
- file_out_stream.write((char *)&yes, sizeof(bool));
- }
- else
- {
- file_out_stream.write((char *)&no, sizeof(bool));
- }
- if (edge_iterator->is_access_restricted)
- {
- file_out_stream.write((char *)&yes, sizeof(bool));
- }
- else
- {
- file_out_stream.write((char *)&no, sizeof(bool));
- }
-
- // cannot take adress of bit field, so use local
- const TravelMode travel_mode = edge_iterator->travel_mode;
- file_out_stream.write((char *)&travel_mode, sizeof(TravelMode));
-
- if (edge_iterator->is_split)
- {
- file_out_stream.write((char *)&yes, sizeof(bool));
- }
- else
- {
- file_out_stream.write((char *)&no, sizeof(bool));
- }
- ++number_of_used_edges;
- }
- ++edge_iterator;
+ all_edges_list[j].result.source = SPECIAL_NODEID;
+ all_edges_list[j].result.target = SPECIAL_NODEID;
}
- TIMER_STOP(set_target_coords);
- std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
+ }
+}
- std::cout << "[extractor] setting number of edges ... " << std::flush;
+void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const
+{
+ std::cout << "[extractor] Writing used egdes ... " << std::flush;
+ TIMER_START(write_edges);
+ // Traverse list of edges and nodes in parallel and set target coord
+ unsigned number_of_used_edges = 0;
- file_out_stream.seekp(previous_file_position);
- file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
- file_out_stream.close();
- std::cout << "ok" << std::endl;
+ auto start_position = file_out_stream.tellp();
+ file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
- std::cout << "[extractor] writing street name index ... " << std::flush;
- TIMER_START(write_name_index);
- std::string name_file_streamName = (output_file_name + ".names");
- boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
+ for (const auto& edge : all_edges_list)
+ {
+ if (edge.result.source == SPECIAL_NODEID || edge.result.target == SPECIAL_NODEID)
+ {
+ continue;
+ }
+
+ file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge));
+ number_of_used_edges++;
+ }
+ TIMER_STOP(write_edges);
+ std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl;
- unsigned total_length = 0;
- std::vector<unsigned> name_lengths;
- for (const std::string &temp_string : name_list)
+ std::cout << "[extractor] setting number of edges ... " << std::flush;
+ file_out_stream.seekp(start_position);
+ file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
+ std::cout << "ok" << std::endl;
+
+ SimpleLogger().Write() << "Processed " << number_of_used_edges << " edges";
+}
+
+void ExtractionContainers::WriteNodes(std::ofstream& file_out_stream) const
+{
+ unsigned number_of_used_nodes = 0;
+ // write dummy value, will be overwritten later
+ file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
+ std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
+ TIMER_START(write_nodes);
+ // identify all used nodes by a merging step of two sorted lists
+ auto node_iterator = all_nodes_list.begin();
+ auto node_id_iterator = used_node_id_list.begin();
+ while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
+ {
+ if (*node_id_iterator < node_iterator->node_id)
{
- const unsigned string_length =
- std::min(static_cast<unsigned>(temp_string.length()), 255u);
- name_lengths.push_back(string_length);
- total_length += string_length;
+ ++node_id_iterator;
+ continue;
}
+ if (*node_id_iterator > node_iterator->node_id)
+ {
+ ++node_iterator;
+ continue;
+ }
+ BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
- RangeTable<> table(name_lengths);
- name_file_stream << table;
+ file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
- name_file_stream.write((char *)&total_length, sizeof(unsigned));
- // write all chars consecutively
- for (const std::string &temp_string : name_list)
+ ++number_of_used_nodes;
+ ++node_id_iterator;
+ ++node_iterator;
+ }
+ TIMER_STOP(write_nodes);
+ std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
+
+ std::cout << "[extractor] setting number of nodes ... " << std::flush;
+ std::ios::pos_type previous_file_position = file_out_stream.tellp();
+ file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
+ file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
+ file_out_stream.seekp(previous_file_position);
+ std::cout << "ok" << std::endl;
+
+ SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes";
+}
+
+void ExtractionContainers::WriteRestrictions(const std::string& path) const
+{
+ // serialize restrictions
+ std::ofstream restrictions_out_stream;
+ unsigned written_restriction_count = 0;
+ restrictions_out_stream.open(path.c_str(), std::ios::binary);
+ const FingerPrint fingerprint = FingerPrint::GetValid();
+ restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
+ const auto count_position = restrictions_out_stream.tellp();
+ restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
+
+ for (const auto &restriction_container : restrictions_list)
+ {
+ if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
+ SPECIAL_NODEID != restriction_container.restriction.via.node &&
+ SPECIAL_NODEID != restriction_container.restriction.to.node)
{
- const unsigned string_length =
- std::min(static_cast<unsigned>(temp_string.length()), 255u);
- name_file_stream.write(temp_string.c_str(), string_length);
+ restrictions_out_stream.write((char *)&(restriction_container.restriction),
+ sizeof(TurnRestriction));
+ ++written_restriction_count;
}
+ }
+ restrictions_out_stream.seekp(count_position);
+ restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
+ restrictions_out_stream.close();
+ SimpleLogger().Write() << "usable restrictions: " << written_restriction_count;
+}
- name_file_stream.close();
- TIMER_STOP(write_name_index);
- std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
+void ExtractionContainers::PrepareRestrictions()
+{
+ std::cout << "[extractor] Sorting used ways ... " << std::flush;
+ TIMER_START(sort_ways);
+ stxxl::sort(way_start_end_id_list.begin(), way_start_end_id_list.end(),
+ FirstAndLastSegmentOfWayStxxlCompare(), stxxl_memory);
+ TIMER_STOP(sort_ways);
+ std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
+
+ std::cout << "[extractor] Sorting " << restrictions_list.size()
+ << " restriction. by from... " << std::flush;
+ TIMER_START(sort_restrictions);
+ stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
+ CmpRestrictionContainerByFrom(), stxxl_memory);
+ TIMER_STOP(sort_restrictions);
+ std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
+
+ std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
+ TIMER_START(fix_restriction_starts);
+ auto restrictions_iterator = restrictions_list.begin();
+ auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
+
+ while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
+ restrictions_iterator != restrictions_list.end())
+ {
+ if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
+ {
+ ++way_start_and_end_iterator;
+ continue;
+ }
+
+ if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
+ {
+ SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.from.way;
+ restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
+ ++restrictions_iterator;
+ continue;
+ }
+
+ BOOST_ASSERT(way_start_and_end_iterator->way_id ==
+ restrictions_iterator->restriction.from.way);
+ // we do not remap the via id yet, since we will need it for the to node as well
+ const NodeID via_node_id = restrictions_iterator->restriction.via.node;
+
+ // check if via is actually valid, if not invalidate
+ auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
+ if(via_id_iter == external_to_internal_node_id_map.end())
+ {
+ SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid node: " << restrictions_iterator->restriction.via.node;
+ restrictions_iterator->restriction.via.node = SPECIAL_NODEID;
+ ++restrictions_iterator;
+ continue;
+ }
- SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
- << number_of_used_edges << " edges";
+ if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
+ {
+ // assign new from node id
+ auto id_iter = external_to_internal_node_id_map.find(
+ way_start_and_end_iterator->first_segment_target_id);
+ BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
+ restrictions_iterator->restriction.from.node = id_iter->second;
+ }
+ else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
+ {
+ // assign new from node id
+ auto id_iter = external_to_internal_node_id_map.find(
+ way_start_and_end_iterator->last_segment_source_id);
+ BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
+ restrictions_iterator->restriction.from.node = id_iter->second;
+ }
+ ++restrictions_iterator;
}
- catch (const std::exception &e)
+
+ TIMER_STOP(fix_restriction_starts);
+ std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
+
+ std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
+ TIMER_START(sort_restrictions_to);
+ stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
+ CmpRestrictionContainerByTo(), stxxl_memory);
+ TIMER_STOP(sort_restrictions_to);
+ std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
+
+ std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
+ TIMER_START(fix_restriction_ends);
+ restrictions_iterator = restrictions_list.begin();
+ way_start_and_end_iterator = way_start_end_id_list.cbegin();
+ while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
+ restrictions_iterator != restrictions_list.end())
{
- std::cerr << "Caught Execption:" << e.what() << std::endl;
+ if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
+ {
+ ++way_start_and_end_iterator;
+ continue;
+ }
+ if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID ||
+ restrictions_iterator->restriction.via.node == SPECIAL_NODEID)
+ {
+ ++restrictions_iterator;
+ continue;
+ }
+ if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
+ {
+ SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.to.way;
+ restrictions_iterator->restriction.to.way = SPECIAL_NODEID;
+ ++restrictions_iterator;
+ continue;
+ }
+ BOOST_ASSERT(way_start_and_end_iterator->way_id ==
+ restrictions_iterator->restriction.to.way);
+ const NodeID via_node_id = restrictions_iterator->restriction.via.node;
+
+ // assign new via node id
+ auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
+ BOOST_ASSERT(via_id_iter != external_to_internal_node_id_map.end());
+ restrictions_iterator->restriction.via.node = via_id_iter->second;
+
+ if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
+ {
+ auto to_id_iter = external_to_internal_node_id_map.find(
+ way_start_and_end_iterator->first_segment_target_id);
+ BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
+ restrictions_iterator->restriction.to.node = to_id_iter->second;
+ }
+ else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
+ {
+ auto to_id_iter = external_to_internal_node_id_map.find(
+ way_start_and_end_iterator->last_segment_source_id);
+ BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
+ restrictions_iterator->restriction.to.node = to_id_iter->second;
+ }
+ ++restrictions_iterator;
}
+ TIMER_STOP(fix_restriction_ends);
+ std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
}
diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp
index d04f595..ef71d05 100644
--- a/extractor/extraction_containers.hpp
+++ b/extractor/extraction_containers.hpp
@@ -32,13 +32,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "first_and_last_segment_of_way.hpp"
#include "../data_structures/external_memory_node.hpp"
#include "../data_structures/restriction.hpp"
-#include "../util/fingerprint.hpp"
#include <stxxl/vector>
+#include <unordered_map>
/**
* Uses external memory containers from stxxl to store all the data that
* is collected by the extractor callbacks.
+ *
+ * The data is the filtered, aggregated and finally written to disk.
*/
class ExtractionContainers
{
@@ -49,6 +51,14 @@ class ExtractionContainers
#else
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
+ void PrepareNodes();
+ void PrepareRestrictions();
+ void PrepareEdges();
+
+ void WriteNodes(std::ofstream& file_out_stream) const;
+ void WriteRestrictions(const std::string& restrictions_file_name) const;
+ void WriteEdges(std::ofstream& file_out_stream) const;
+ void WriteNames(const std::string& names_file_name) const;
public:
using STXXLNodeIDVector = stxxl::vector<NodeID>;
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
@@ -63,14 +73,15 @@ class ExtractionContainers
STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
- const FingerPrint fingerprint;
+ std::unordered_map<NodeID, NodeID> external_to_internal_node_id_map;
ExtractionContainers();
~ExtractionContainers();
void PrepareData(const std::string &output_file_name,
- const std::string &restrictions_file_name);
+ const std::string &restrictions_file_name,
+ const std::string &names_file_name);
};
#endif /* EXTRACTION_CONTAINERS_HPP */
diff --git a/extractor/extraction_helper_functions.hpp b/extractor/extraction_helper_functions.hpp
index d10200a..e61e543 100644
--- a/extractor/extraction_helper_functions.hpp
+++ b/extractor/extraction_helper_functions.hpp
@@ -102,7 +102,7 @@ unsigned parseDuration(const std::string &s)
minutes = cast::string_to_int(result[1]);
hours = cast::string_to_int(result[0]);
}
- return 10 * (3600 * hours + 60 * minutes + seconds);
+ return (3600 * hours + 60 * minutes + seconds);
}
}
else if (iso_8601_duration_is_valid(s))
diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp
index fce0f88..c1a0a21 100644
--- a/extractor/extractor.cpp
+++ b/extractor/extractor.cpp
@@ -82,7 +82,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* .restrictions : Turn restrictions that are used my osrm-prepare to construct the edge-expanded graph
*
*/
-int extractor::run(const ExtractorConfig &extractor_config)
+int extractor::run()
{
try
{
@@ -91,20 +91,20 @@ int extractor::run(const ExtractorConfig &extractor_config)
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
const auto number_of_threads =
- std::min(recommended_num_threads, extractor_config.requested_num_threads);
+ std::min(recommended_num_threads, config.requested_num_threads);
tbb::task_scheduler_init init(number_of_threads);
- SimpleLogger().Write() << "Input file: " << extractor_config.input_path.filename().string();
- SimpleLogger().Write() << "Profile: " << extractor_config.profile_path.filename().string();
+ SimpleLogger().Write() << "Input file: " << config.input_path.filename().string();
+ SimpleLogger().Write() << "Profile: " << config.profile_path.filename().string();
SimpleLogger().Write() << "Threads: " << number_of_threads;
// setup scripting environment
- ScriptingEnvironment scripting_environment(extractor_config.profile_path.string().c_str());
+ ScriptingEnvironment scripting_environment(config.profile_path.string().c_str());
ExtractionContainers extraction_containers;
auto extractor_callbacks = osrm::make_unique<ExtractorCallbacks>(extraction_containers);
- const osmium::io::File input_file(extractor_config.input_path.string());
+ const osmium::io::File input_file(config.input_path.string());
osmium::io::Reader reader(input_file);
const osmium::io::Header header = reader.header();
@@ -131,7 +131,7 @@ int extractor::run(const ExtractorConfig &extractor_config)
}
SimpleLogger().Write() << "timestamp: " << timestamp;
- boost::filesystem::ofstream timestamp_out(extractor_config.timestamp_file_name);
+ boost::filesystem::ofstream timestamp_out(config.timestamp_file_name);
timestamp_out.write(timestamp.c_str(), timestamp.length());
timestamp_out.close();
@@ -236,12 +236,13 @@ int extractor::run(const ExtractorConfig &extractor_config)
return 1;
}
- extraction_containers.PrepareData(extractor_config.output_file_name,
- extractor_config.restriction_file_name);
+ extraction_containers.PrepareData(config.output_file_name,
+ config.restriction_file_name,
+ config.names_file_name);
TIMER_STOP(extracting);
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
SimpleLogger().Write() << "To prepare the data for routing, run: "
- << "./osrm-prepare " << extractor_config.output_file_name
+ << "./osrm-prepare " << config.output_file_name
<< std::endl;
}
catch (std::exception &e)
diff --git a/extractor/extractor.hpp b/extractor/extractor.hpp
index 8ea56c3..72defca 100644
--- a/extractor/extractor.hpp
+++ b/extractor/extractor.hpp
@@ -30,8 +30,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "extractor_options.hpp"
-struct extractor
+class extractor
{
- int run(const ExtractorConfig &extractor_config);
+public:
+ extractor(const ExtractorConfig &extractor_config)
+ : config(extractor_config) {}
+ int run();
+private:
+ ExtractorConfig config;
};
#endif /* EXTRACTOR_HPP */
diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp
index deef831..bab309d 100644
--- a/extractor/extractor_callbacks.cpp
+++ b/extractor/extractor_callbacks.cpp
@@ -108,17 +108,40 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
<< " of size " << input_way.nodes().size();
return;
}
+
+ InternalExtractorEdge::WeightData forward_weight_data;
+ InternalExtractorEdge::WeightData backward_weight_data;
+
if (0 < parsed_way.duration)
{
- // TODO: iterate all way segments and set duration corresponding to the length of each
- // segment
- const_cast<ExtractionWay &>(parsed_way).forward_speed =
- parsed_way.duration / (input_way.nodes().size() - 1);
- const_cast<ExtractionWay &>(parsed_way).backward_speed =
- parsed_way.duration / (input_way.nodes().size() - 1);
+ const unsigned num_edges = (input_way.nodes().size() - 1);
+ // FIXME We devide by the numer of nodes here, but should rather consider
+ // the length of each segment. We would eigther have to compute the length
+ // of the whole way here (we can't: no node coordinates) or push that back
+ // to the container and keep a reference to the way.
+ forward_weight_data.duration = parsed_way.duration / num_edges;
+ forward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
+ backward_weight_data.duration = parsed_way.duration / num_edges;
+ backward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
+ }
+ else
+ {
+ if (parsed_way.forward_speed > 0 &&
+ parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
+ {
+ forward_weight_data.speed = parsed_way.forward_speed;
+ forward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
+ }
+ if (parsed_way.backward_speed > 0 &&
+ parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
+ {
+ backward_weight_data.speed = parsed_way.backward_speed;
+ backward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
+ }
}
- if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
+ if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID
+ && backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID)
{
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << input_way.id();
return;
@@ -144,36 +167,34 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
((parsed_way.forward_speed != parsed_way.backward_speed) ||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
- auto pair_wise_segment_split =
+ // lambda to add edge to container
+ auto pair_wise_segment_split_forward =
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
{
- // SimpleLogger().Write() << "adding edge (" << first_node.ref() << "," <<
- // last_node.ref() << "), fwd speed: " << parsed_way.forward_speed;
+ const bool forward_only = split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode;
external_memory.all_edges_list.push_back(InternalExtractorEdge(
- first_node.ref(), last_node.ref(),
- ((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)
- ? ExtractionWay::oneway
- : ExtractionWay::bidirectional),
- parsed_way.forward_speed, name_id, parsed_way.roundabout, parsed_way.ignore_in_grid,
- (0 < parsed_way.duration), parsed_way.is_access_restricted,
- parsed_way.forward_travel_mode, split_edge));
+ first_node.ref(), last_node.ref(), name_id, forward_weight_data,
+ true, !forward_only, parsed_way.roundabout, parsed_way.ignore_in_grid,
+ parsed_way.is_access_restricted, parsed_way.forward_travel_mode, split_edge));
external_memory.used_node_id_list.push_back(first_node.ref());
};
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
+ // traverse way in reverse in this case
if (is_opposite_way)
{
+ // why don't we have to swap the parsed_way.forward/backward speed here as well
const_cast<ExtractionWay &>(parsed_way).forward_travel_mode =
parsed_way.backward_travel_mode;
const_cast<ExtractionWay &>(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(),
- pair_wise_segment_split);
+ pair_wise_segment_split_forward);
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
}
else
{
osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(),
- pair_wise_segment_split);
+ pair_wise_segment_split_forward);
external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
}
@@ -187,22 +208,19 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
if (split_edge)
{ // Only true if the way should be split
- BOOST_ASSERT(parsed_way.backward_travel_mode > 0);
+ BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
auto pair_wise_segment_split_2 =
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
{
- // SimpleLogger().Write() << "adding edge (" << last_node.ref() << "," <<
- // first_node.ref() << "), bwd speed: " << parsed_way.backward_speed;
external_memory.all_edges_list.push_back(InternalExtractorEdge(
- last_node.ref(), first_node.ref(), ExtractionWay::oneway, parsed_way.backward_speed,
- name_id, parsed_way.roundabout, parsed_way.ignore_in_grid,
- (0 < parsed_way.duration), parsed_way.is_access_restricted,
- parsed_way.backward_travel_mode, split_edge));
+ last_node.ref(), first_node.ref(), name_id, backward_weight_data,
+ true, false, parsed_way.roundabout, parsed_way.ignore_in_grid,
+ parsed_way.is_access_restricted, parsed_way.backward_travel_mode, split_edge));
+ external_memory.used_node_id_list.push_back(last_node.ref());
};
if (is_opposite_way)
{
- // SimpleLogger().Write() << "opposite2";
osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(),
pair_wise_segment_split_2);
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
@@ -211,7 +229,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
{
osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(),
pair_wise_segment_split_2);
- external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
+ external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
}
external_memory.way_start_end_id_list.push_back(
diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp
index 9ae5cd4..23cbacc 100644
--- a/extractor/extractor_options.cpp
+++ b/extractor/extractor_options.cpp
@@ -135,6 +135,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
boost::filesystem::path &input_path = extractor_config.input_path;
extractor_config.output_file_name = input_path.string();
extractor_config.restriction_file_name = input_path.string();
+ extractor_config.names_file_name = input_path.string();
extractor_config.timestamp_file_name = input_path.string();
std::string::size_type pos = extractor_config.output_file_name.find(".osm.bz2");
if (pos == std::string::npos)
@@ -156,12 +157,14 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
{
extractor_config.output_file_name.append(".osrm");
extractor_config.restriction_file_name.append(".osrm.restrictions");
+ extractor_config.names_file_name.append(".osrm.names");
extractor_config.timestamp_file_name.append(".osrm.timestamp");
}
else
{
extractor_config.output_file_name.replace(pos, 5, ".osrm");
extractor_config.restriction_file_name.replace(pos, 5, ".osrm.restrictions");
+ extractor_config.names_file_name.replace(pos, 5, ".osrm.names");
extractor_config.timestamp_file_name.replace(pos, 5, ".osrm.timestamp");
}
}
@@ -169,6 +172,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
{
extractor_config.output_file_name.replace(pos, 8, ".osrm");
extractor_config.restriction_file_name.replace(pos, 8, ".osrm.restrictions");
+ extractor_config.names_file_name.replace(pos, 8, ".osrm.names");
extractor_config.timestamp_file_name.replace(pos, 8, ".osrm.timestamp");
}
}
diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp
index 5712ea0..c164f6a 100644
--- a/extractor/extractor_options.hpp
+++ b/extractor/extractor_options.hpp
@@ -48,6 +48,7 @@ struct ExtractorConfig
std::string output_file_name;
std::string restriction_file_name;
+ std::string names_file_name;
std::string timestamp_file_name;
unsigned requested_num_threads;
diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp
index 27e1af1..15f3c0d 100644
--- a/extractor/internal_extractor_edge.hpp
+++ b/extractor/internal_extractor_edge.hpp
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h"
#include "../data_structures/travel_mode.hpp"
+#include "../data_structures/import_edge.hpp"
#include <boost/assert.hpp>
@@ -37,83 +38,108 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct InternalExtractorEdge
{
- InternalExtractorEdge()
- : start(0), target(0), speed(0), name_id(0), direction(0), is_roundabout(false),
- is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
- is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
+ // specify the type of the weight data
+ enum class WeightType : char {
+ INVALID,
+ SPEED,
+ EDGE_DURATION,
+ WAY_DURATION,
+ };
+
+ struct WeightData
+ {
+
+ WeightData() : duration(0.0), type(WeightType::INVALID)
+ {
+ }
+
+ union
+ {
+ double duration;
+ double speed;
+ };
+ WeightType type;
+ };
+
+ explicit InternalExtractorEdge()
+ : result(0, 0, 0, 0, false, false, false, false, false,
+ TRAVEL_MODE_INACCESSIBLE, false)
{
}
- explicit InternalExtractorEdge(NodeID start,
- NodeID target,
- short direction,
- double speed,
- unsigned name_id,
- bool is_roundabout,
- bool is_in_tiny_cc,
- bool is_duration_set,
- bool is_access_restricted,
- TravelMode travel_mode,
- bool is_split)
- : start(start), target(target), speed(speed), name_id(name_id), direction(direction),
- is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
- is_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
- is_split(is_split), travel_mode(travel_mode)
+ explicit InternalExtractorEdge(NodeID source,
+ NodeID target,
+ NodeID name_id,
+ const WeightData& weight_data,
+ bool forward,
+ bool backward,
+ bool roundabout,
+ bool in_tiny_cc,
+ bool access_restricted,
+ TravelMode travel_mode,
+ bool is_split)
+ : result(source, target, name_id, 0, forward, backward, roundabout,
+ in_tiny_cc, access_restricted, travel_mode, is_split),
+ weight_data(weight_data)
{
}
+ // data that will be written to disk
+ NodeBasedEdge result;
+ // intermediate edge weight
+ WeightData weight_data;
+ // coordinate of the source node
+ FixedPointCoordinate source_coordinate;
+
+
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value()
{
- return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false,
- TRAVEL_MODE_INACCESSIBLE, false);
+ return InternalExtractorEdge(0, 0, 0, WeightData(), false, false, false,
+ false, false, TRAVEL_MODE_INACCESSIBLE, false);
}
static InternalExtractorEdge max_value()
{
- return InternalExtractorEdge(SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false,
- false, TRAVEL_MODE_INACCESSIBLE, false);
+ return InternalExtractorEdge(SPECIAL_NODEID, SPECIAL_NODEID, 0, WeightData(), false, false,
+ false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
}
+};
- NodeID start;
- NodeID target;
- double speed;
- unsigned name_id;
- short direction;
- bool is_roundabout : 1;
- bool is_in_tiny_cc : 1;
- bool is_duration_set : 1;
- bool is_access_restricted : 1;
- bool is_split : 1;
- TravelMode travel_mode : 4;
+struct CmpEdgeByStartThenTargetID
+{
+ using value_type = InternalExtractorEdge;
+ bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
+ {
+ return (lhs.result.source < rhs.result.source) ||
+ ((lhs.result.source == rhs.result.source) &&
+ (lhs.result.target < rhs.result.target));
+ }
- FixedPointCoordinate source_coordinate;
- FixedPointCoordinate target_coordinate;
+ value_type max_value() { return InternalExtractorEdge::max_value(); }
+ value_type min_value() { return InternalExtractorEdge::min_value(); }
};
struct CmpEdgeByStartID
{
using value_type = InternalExtractorEdge;
- bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
+ bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
- return a.start < b.start;
+ return lhs.result.source < rhs.result.source;
}
value_type max_value() { return InternalExtractorEdge::max_value(); }
-
value_type min_value() { return InternalExtractorEdge::min_value(); }
};
struct CmpEdgeByTargetID
{
using value_type = InternalExtractorEdge;
-
- bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
+ bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
- return a.target < b.target;
+ return lhs.result.target < rhs.result.target;
}
value_type max_value() { return InternalExtractorEdge::max_value(); }
-
value_type min_value() { return InternalExtractorEdge::min_value(); }
};
diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp
index 77dae9c..9b209b7 100644
--- a/extractor/restriction_parser.cpp
+++ b/extractor/restriction_parser.cpp
@@ -44,7 +44,7 @@ namespace
{
int lua_error_callback(lua_State *lua_state)
{
- luabind::object error_msg(luabind::from_stack(lua_state, -1));
+ std::string error_msg = lua_tostring(lua_state, -1);
std::ostringstream error_stream;
error_stream << error_msg;
throw osrm::exception("ERROR occured in profile script:\n" + error_stream.str());
diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp
index 9727722..b32ab4b 100644
--- a/extractor/scripting_environment.cpp
+++ b/extractor/scripting_environment.cpp
@@ -53,7 +53,7 @@ auto get_value_by_key(T const &object, const char *key) -> decltype(object.get_v
int lua_error_callback(lua_State *L) // This is so I can use my own function as an
// exception handler, pcall_log()
{
- luabind::object error_msg(luabind::from_stack(L, -1));
+ std::string error_msg = lua_tostring(L, -1);
std::ostringstream error_stream;
error_stream << error_msg;
throw osrm::exception("ERROR occured in profile script:\n" + error_stream.str());
diff --git a/features/bicycle/access.feature b/features/bicycle/access.feature
index 2087327..3a2fffb 100644
--- a/features/bicycle/access.feature
+++ b/features/bicycle/access.feature
@@ -120,7 +120,7 @@ Feature: Bike - Access tags on ways
| no | | | |
| private | | | |
| agricultural | | | |
- | forestery | | | |
+ | forestry | | | |
| | yes | | x |
| | permissive | | x |
| | designated | | x |
@@ -128,7 +128,7 @@ Feature: Bike - Access tags on ways
| | no | | |
| | private | | |
| | agricultural | | |
- | | forestery | | |
+ | | forestry | | |
| | | yes | x |
| | | permissive | x |
| | | designated | x |
@@ -136,7 +136,7 @@ Feature: Bike - Access tags on ways
| | | no | |
| | | private | |
| | | agricultural | |
- | | | forestery | |
+ | | | forestry | |
Scenario: Bike - Access tags on both node and way
Then routability should be
diff --git a/features/bicycle/access_node.feature b/features/bicycle/access_node.feature
index 5a6f2b5..05e94fe 100644
--- a/features/bicycle/access_node.feature
+++ b/features/bicycle/access_node.feature
@@ -7,20 +7,21 @@ Feature: Bike - Access tags on nodes
Scenario: Bike - Access tag hierachy on nodes
Then routability should be
- | node/access | node/vehicle | node/bicycle | bothw |
- | | | | x |
- | yes | | | x |
- | no | | | |
- | | yes | | x |
- | | no | | |
- | no | yes | | x |
- | yes | no | | |
- | | | yes | x |
- | | | no | |
- | no | | yes | x |
- | yes | | no | |
- | | no | yes | x |
- | | yes | no | |
+ | node/access | node/vehicle | node/bicycle | node/highway | bothw |
+ | | | | | x |
+ | yes | | | | x |
+ | no | | | | |
+ | | yes | | | x |
+ | | no | | | |
+ | no | yes | | | x |
+ | yes | no | | | |
+ | | | yes | | x |
+ | | | no | | |
+ | | | no | crossing | x |
+ | no | | yes | | x |
+ | yes | | no | | |
+ | | no | yes | | x |
+ | | yes | no | | |
Scenario: Bike - Overwriting implied acccess on nodes doesn't overwrite way
Then routability should be
@@ -45,7 +46,7 @@ Feature: Bike - Access tags on nodes
| no | | | |
| private | | | |
| agricultural | | | |
- | forestery | | | |
+ | forestry | | | |
| | yes | | x |
| | permissive | | x |
| | designated | | x |
@@ -53,7 +54,7 @@ Feature: Bike - Access tags on nodes
| | no | | |
| | private | | |
| | agricultural | | |
- | | forestery | | |
+ | | forestry | | |
| | | yes | x |
| | | permissive | x |
| | | designated | x |
@@ -61,4 +62,4 @@ Feature: Bike - Access tags on nodes
| | | no | |
| | | private | |
| | | agricultural | |
- | | | forestery | |
+ | | | forestry | |
diff --git a/features/bicycle/surface.feature b/features/bicycle/surface.feature
index 216307b..8d303aa 100644
--- a/features/bicycle/surface.feature
+++ b/features/bicycle/surface.feature
@@ -16,7 +16,7 @@ Feature: Bike - Surfaces
| cycleway | unpaved | 120s |
| cycleway | fine_gravel | 120s |
| cycleway | gravel | 120s |
- | cycleway | pebbelstone | 120s |
+ | cycleway | pebblestone | 120s |
| cycleway | dirt | 120s |
| cycleway | earth | 120s |
| cycleway | grass | 120s |
diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature
index 781f4c6..84cfa4f 100644
--- a/features/car/maxspeed.feature
+++ b/features/car/maxspeed.feature
@@ -93,3 +93,22 @@ OSRM will use 4/5 of the projected free-flow speed.
| primary | 15 | | 30 | 60 | 34 km/h | 59 km/h |
| primary | 15 | 3 | 30 | 60 | 15 km/h | 30 km/h |
+ Scenario: Car - Single lane streets be ignored or incur a penalty
+ Then routability should be
+
+ | highway | maxspeed | lanes | maxspeed:forward | maxspeed:backward | forw | backw |
+ | primary | | | | | 63 km/h | 63 km/h |
+ | primary | | 1 | | | 32 km/h | 32 km/h |
+ | primary | 60 | | | | 59 km/h | 59 km/h |
+ | primary | 60 | 1 | | | 30 km/h | 30 km/h |
+ | primary | | | 60 | | 59 km/h | 63 km/h |
+ | primary | | 1 | 60 | | 30 km/h | 32 km/h |
+ | primary | | | | 60 | 63 km/h | 59 km/h |
+ | primary | | 1 | | 60 | 32 km/h | 30 km/h |
+ | primary | 15 | | 60 | | 59 km/h | 23 km/h |
+ | primary | 15 | 1 | 60 | | 30 km/h | 7 km/h |
+ | primary | 15 | | | 60 | 23 km/h | 59 km/h |
+ | primary | 15 | 1 | | 60 | 7 km/h | 30 km/h |
+ | primary | 15 | | 30 | 60 | 34 km/h | 59 km/h |
+ | primary | 15 | 1 | 30 | 60 | 15 km/h | 30 km/h |
+
diff --git a/features/car/names.feature b/features/car/names.feature
index ac4bfc8..b6a95ae 100644
--- a/features/car/names.feature
+++ b/features/car/names.feature
@@ -10,13 +10,13 @@ Feature: Car - Street names in instructions
| | c |
And the ways
- | nodes | name |
- | ab | My Way |
- | bc | Your Way |
+ | nodes | name | ref |
+ | ab | My Way | |
+ | bc | Your Way | A1 |
When I route I should get
- | from | to | route |
- | a | c | My Way,Your Way |
+ | from | to | route |
+ | a | c | My Way,Your Way (A1) |
@todo
Scenario: Car - Use way type to describe unnamed ways
diff --git a/features/foot/access.feature b/features/foot/access.feature
index 4d81d0e..353076c 100644
--- a/features/foot/access.feature
+++ b/features/foot/access.feature
@@ -51,7 +51,7 @@ Feature: Foot - Access tags on ways
| no | | |
| private | | |
| agricultural | | |
- | forestery | | |
+ | forestry | | |
| | yes | x |
| | permissive | x |
| | designated | x |
@@ -59,7 +59,7 @@ Feature: Foot - Access tags on ways
| | no | |
| | private | |
| | agricultural | |
- | | forestery | |
+ | | forestry | |
Scenario: Foot - Access tags on both node and way
Then routability should be
diff --git a/features/foot/access_node.feature b/features/foot/access_node.feature
index 5a4a131..8519d05 100644
--- a/features/foot/access_node.feature
+++ b/features/foot/access_node.feature
@@ -39,7 +39,7 @@ Feature: Foot - Access tags on nodes
| no | | |
| private | | |
| agricultural | | |
- | forestery | | |
+ | forestry | | |
| no | yes | x |
| no | permissive | x |
| no | designated | x |
@@ -47,4 +47,4 @@ Feature: Foot - Access tags on nodes
| yes | no | |
| yes | private | |
| yes | agricultural | |
- | yes | forestery | |
+ | yes | forestry | |
diff --git a/features/foot/surface.feature b/features/foot/surface.feature
index 556c3d8..9bcd80c 100644
--- a/features/foot/surface.feature
+++ b/features/foot/surface.feature
@@ -10,6 +10,6 @@ Feature: Foot - Surfaces
| footway | | 145s ~10% |
| footway | fine_gravel | 193s ~10% |
| footway | gravel | 193s ~10% |
- | footway | pebbelstone | 193s ~10% |
+ | footway | pebblestone | 193s ~10% |
| footway | mud | 289s ~10% |
| footway | sand | 289s ~10% |
diff --git a/features/foot/way.feature b/features/foot/way.feature
index 653c773..ff3314f 100644
--- a/features/foot/way.feature
+++ b/features/foot/way.feature
@@ -30,3 +30,9 @@ Feature: Foot - Accessability of different way types
| pier | x |
| cycleway | |
| bridleway | |
+
+ Scenario: Foot - Basic access
+ Then routability should be
+ | highway | leisure | forw |
+ | (nil) | track | x |
+
diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature
index 08e6652..75dbc6e 100644
--- a/features/nearest/pick.feature
+++ b/features/nearest/pick.feature
@@ -57,14 +57,13 @@ Feature: Locating Nearest node on a Way - pick closest way
Scenario: Nearest - High lat/lon
Given the node locations
- | node | lat | lon |
- | a | -85 | -180 |
- | b | -85 | -160 |
- | c | -85 | -140 |
- | x | 75 | -180 |
- | y | 75 | -180 |
- | v | 1 | 1 |
- | w | -1 | -1 |
+ | node | lat | lon |
+ | a | -85 | -180 |
+ | b | -85 | -160 |
+ | c | -85 | -140 |
+ | x | -84.999 | -180 |
+ | y | -84.999 | -160 |
+ | z | -84.999 | -140 |
And the ways
| nodes |
@@ -73,6 +72,5 @@ Feature: Locating Nearest node on a Way - pick closest way
When I request nearest I should get
| in | out |
| x | a |
- | y | a |
- | v | c |
- | w | c |
+ | y | b |
+ | z | c |
diff --git a/features/options/prepare/help.feature b/features/options/prepare/help.feature
index 49497ae..dae522d 100644
--- a/features/options/prepare/help.feature
+++ b/features/options/prepare/help.feature
@@ -17,7 +17,7 @@ Feature: osrm-prepare command line options: help
And stdout should contain "--profile"
And stdout should contain "--threads"
And stdout should contain 15 lines
- And it should exit with code 0
+ And it should exit with code 1
Scenario: osrm-prepare - Help, short
When I run "osrm-prepare -h"
diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb
index f1e58ba..524fd32 100644
--- a/features/step_definitions/data.rb
+++ b/features/step_definitions/data.rb
@@ -174,3 +174,7 @@ end
Given /^data is loaded with datastore$/ do
@load_method = 'datastore'
end
+
+Given /^the HTTP method "([^"]*)"$/ do |method|
+ @http_method = method
+end
diff --git a/features/step_definitions/distance_matrix.rb b/features/step_definitions/distance_matrix.rb
index f85bdcc..8c4e927 100644
--- a/features/step_definitions/distance_matrix.rb
+++ b/features/step_definitions/distance_matrix.rb
@@ -52,5 +52,5 @@ When /^I request a travel time matrix I should get$/ do |table|
actual << r
end
end
- table.routing_diff! actual
+ table.diff! actual
end
diff --git a/features/step_definitions/locate.rb b/features/step_definitions/locate.rb
index 3e67be3..2fd8e62 100644
--- a/features/step_definitions/locate.rb
+++ b/features/step_definitions/locate.rb
@@ -9,7 +9,7 @@ When /^I request locate I should get$/ do |table|
out_node = find_node_by_name row['out']
raise "*** unknown out-node '#{row['out']}" unless out_node
- response = request_locate("#{in_node.lat},#{in_node.lon}")
+ response = request_locate(in_node)
if response.code == "200" && response.body.empty? == false
json = JSON.parse response.body
if json['status'] == 0
@@ -39,7 +39,7 @@ When /^I request locate I should get$/ do |table|
actual << got
end
end
- table.routing_diff! actual
+ table.diff! actual
end
When /^I request locate (\d+) times I should get$/ do |n,table|
diff --git a/features/step_definitions/matching.rb b/features/step_definitions/matching.rb
index 3f3181f..e9b7234 100644
--- a/features/step_definitions/matching.rb
+++ b/features/step_definitions/matching.rb
@@ -91,6 +91,6 @@ When /^I match I should get$/ do |table|
actual << got
end
end
- table.routing_diff! actual
+ table.diff! actual
end
diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb
index 532c1f0..481c741 100644
--- a/features/step_definitions/nearest.rb
+++ b/features/step_definitions/nearest.rb
@@ -9,7 +9,7 @@ When /^I request nearest I should get$/ do |table|
out_node = find_node_by_name row['out']
raise "*** unknown out-node '#{row['out']}" unless out_node
- response = request_nearest("#{in_node.lat},#{in_node.lon}")
+ response = request_nearest(in_node)
if response.code == "200" && response.body.empty? == false
json = JSON.parse response.body
if json['status'] == 0
@@ -39,7 +39,7 @@ When /^I request nearest I should get$/ do |table|
actual << got
end
end
- table.routing_diff! actual
+ table.diff! actual
end
When /^I request nearest (\d+) times I should get$/ do |n,table|
diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb
index dcbde5a..a9241be 100644
--- a/features/step_definitions/routability.rb
+++ b/features/step_definitions/routability.rb
@@ -74,5 +74,5 @@ Then /^routability should be$/ do |table|
actual << output_row
end
end
- table.routing_diff! actual
+ table.diff! actual
end
diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb
index c25f5b7..597ea65 100644
--- a/features/step_definitions/routing.rb
+++ b/features/step_definitions/routing.rb
@@ -140,7 +140,7 @@ When /^I route I should get$/ do |table|
actual << got
end
end
- table.routing_diff! actual
+ table.diff! actual
end
When /^I route (\d+) times I should get$/ do |n,table|
diff --git a/features/support/cucumber.rb b/features/support/cucumber.rb
deleted file mode 100644
index a43082a..0000000
--- a/features/support/cucumber.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#monkey patch cucumber table class to reorder output.
-#we always want failed rows to be shown right below the expected row.
-
-class Cucumber::Ast::Table
- def routing_diff!(other_table, options={})
- options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options)
-
- other_table = ensure_table(other_table)
- other_table.convert_headers!
- other_table.convert_columns!
- ensure_green!
-
- convert_headers!
- convert_columns!
-
- original_width = cell_matrix[0].length
- other_table_cell_matrix = pad!(other_table.cell_matrix)
- padded_width = cell_matrix[0].length
-
- missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
- surplus_col = padded_width > original_width
-
- require_diff_lcs
- cell_matrix.extend(Diff::LCS)
- changes = cell_matrix.diff(other_table_cell_matrix).flatten
-
- inserted = 0
- missing = 0
-
- row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
-
- last_change = nil
- missing_row_pos = nil
- insert_row_pos = nil
-
- changes.each do |change|
- if(change.action == '-')
- missing_row_pos = change.position + inserted
- cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
- row_indices.insert(missing_row_pos, nil)
- missing += 1
- else # '+'
- #change index so we interleave instead
- insert_row_pos = change.position + inserted + 1
- #insert_row_pos = change.position + missing #original
-
- inserted_row = change.element
- inserted_row.each{|cell| cell.status = :comment}
- cell_matrix.insert(insert_row_pos, inserted_row)
- row_indices[insert_row_pos] = nil
- inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
- inserted += 1
- end
- last_change = change
- end
-
- other_table_cell_matrix.each_with_index do |other_row, i|
- row_index = row_indices.index(i)
- row = cell_matrix[row_index] if row_index
- if row
- (original_width..padded_width).each do |col_index|
- surplus_cell = other_row[col_index]
- row[col_index].value = surplus_cell.value if row[col_index]
- end
- end
- end
-
- clear_cache!
- should_raise =
- missing_row_pos && options[:missing_row] ||
- insert_row_pos && options[:surplus_row] ||
- missing_col && options[:missing_col] ||
- surplus_col && options[:surplus_col]
- raise Different.new(self) if should_raise
- end
-end
\ No newline at end of file
diff --git a/features/support/env.rb b/features/support/env.rb
index f9a4fe4..ea74959 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -22,10 +22,10 @@ SHUTDOWN_TIMEOUT = 10
DEFAULT_LOAD_METHOD = 'datastore'
OSRM_ROUTED_LOG_FILE = 'osrm-routed.log'
-if ENV['OS']==/Windows.*/ then
- TERMSIGNAL='TERM'
-else
+if ENV['OS']=~/Windows.*/ then
TERMSIGNAL=9
+else
+ TERMSIGNAL='TERM'
end
@@ -72,8 +72,8 @@ end
def verify_existance_of_binaries
["osrm-extract", "osrm-prepare", "osrm-routed"].each do |bin|
- unless File.exists? "#{BIN_PATH}/#{bin}"
- raise "*** #{BIN_PATH}/#{bin} is missing. Build failed?"
+ unless File.exists? "#{BIN_PATH}/#{bin}#{EXE}"
+ raise "*** #{BIN_PATH}/#{bin}#{EXE} is missing. Build failed?"
end
end
end
diff --git a/features/support/hooks.rb b/features/support/hooks.rb
index 3370142..2ad49dc 100644
--- a/features/support/hooks.rb
+++ b/features/support/hooks.rb
@@ -4,22 +4,16 @@ STRESS_TIMEOUT = 300
Before do |scenario|
- # feature name
+ # fetch scenario and feature name, so we can use it in log files if needed
case scenario
- when Cucumber::Ast::Scenario
+ when Cucumber::RunningTestCase::Scenario
@feature_name = scenario.feature.name
- when Cucumber::Ast::OutlineTable::ExampleRow
- @feature_name = scenario.scenario_outline.feature.name
- end
-
- # scenario name
- case scenario
- when Cucumber::Ast::Scenario
@scenario_title = scenario.name
- when Cucumber::Ast::OutlineTable::ExampleRow
+ when Cucumber::RunningTestCase::ExampleRow
+ @feature_name = scenario.scenario_outline.feature.name
@scenario_title = scenario.scenario_outline.name
end
-
+
@load_method = DEFAULT_LOAD_METHOD
@query_params = {}
@scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ")
diff --git a/features/support/http.rb b/features/support/http.rb
new file mode 100644
index 0000000..80dad8a
--- /dev/null
+++ b/features/support/http.rb
@@ -0,0 +1,34 @@
+require 'net/http'
+
+def generate_request_url path
+ if @http_method.eql? "POST"
+ pos = path.index('?') - 1
+ service = path[0..pos]
+ uri = URI.parse "#{HOST}/#{service}"
+ else
+ uri = URI.parse "#{HOST}/#{path}"
+ end
+end
+
+def send_request uri, waypoints=[], options={}, timestamps=[]
+ @query = uri.to_s
+ Timeout.timeout(OSRM_TIMEOUT) do
+ if @http_method.eql? "POST"
+ datas = {}
+ if waypoints.length > 0
+ datas[:loc] = waypoints.compact.map { |w| "#{w.lat},#{w.lon}" }
+ end
+ if timestamps.length > 0
+ datas[:t] = timestamps.compact.map { |t| "#{t}" }
+ end
+ datas.merge! options
+ response = Net::HTTP.post_form uri, datas
+ else
+ response = Net::HTTP.get_response uri
+ end
+ end
+rescue Errno::ECONNREFUSED => e
+ raise "*** osrm-routed is not running."
+rescue Timeout::Error
+ raise "*** osrm-routed did not respond."
+end
diff --git a/features/support/locate.rb b/features/support/locate.rb
index 9007247..a62e53a 100644
--- a/features/support/locate.rb
+++ b/features/support/locate.rb
@@ -1,17 +1,12 @@
require 'net/http'
-def request_locate_url path
+def request_locate_url path, node
@query = path
- uri = URI.parse "#{HOST}/#{path}"
- Timeout.timeout(OSRM_TIMEOUT) do
- Net::HTTP.get_response uri
- end
-rescue Errno::ECONNREFUSED => e
- raise "*** osrm-routed is not running."
-rescue Timeout::Error
- raise "*** osrm-routed did not respond."
+
+ uri = generate_request_url path
+ response = send_request uri, [node]
end
-def request_locate a
- request_locate_url "locate?loc=#{a}"
+def request_locate node
+ request_locate_url "locate?loc=#{node.lat},#{node.lon}", node
end
diff --git a/features/support/match.rb b/features/support/match.rb
index bf51189..8bcf7a2 100644
--- a/features/support/match.rb
+++ b/features/support/match.rb
@@ -13,14 +13,8 @@ def request_matching trace=[], timestamps=[], options={}
end
params = (trace_params + defaults.merge(options).to_param).join('&')
params = nil if params==""
- uri = URI.parse ["#{HOST}/match", params].compact.join('?')
- @query = uri.to_s
- Timeout.timeout(OSRM_TIMEOUT) do
- Net::HTTP.get_response uri
- end
-rescue Errno::ECONNREFUSED => e
- raise "*** osrm-routed is not running."
-rescue Timeout::Error
- raise "*** osrm-routed did not respond."
+
+ uri = generate_request_url ("match" + '?' + params)
+ response = send_request uri, trace, options, timestamps
end
diff --git a/features/support/nearest.rb b/features/support/nearest.rb
index 77fc351..af52b49 100644
--- a/features/support/nearest.rb
+++ b/features/support/nearest.rb
@@ -1,17 +1,12 @@
require 'net/http'
-def request_nearest_url path
+def request_nearest_url path, node
@query = path
- uri = URI.parse "#{HOST}/#{path}"
- Timeout.timeout(OSRM_TIMEOUT) do
- Net::HTTP.get_response uri
- end
-rescue Errno::ECONNREFUSED => e
- raise "*** osrm-routed is not running."
-rescue Timeout::Error
- raise "*** osrm-routed did not respond."
+
+ uri = generate_request_url path
+ response = send_request uri, [node]
end
-def request_nearest a
- request_nearest_url "nearest?loc=#{a}"
+def request_nearest node
+ request_nearest_url "nearest?loc=#{node.lat},#{node.lon}", node
end
diff --git a/features/support/route.rb b/features/support/route.rb
index a8c7822..ca353d6 100644
--- a/features/support/route.rb
+++ b/features/support/route.rb
@@ -15,15 +15,13 @@ def request_path path, waypoints=[], options={}
locs = waypoints.compact.map { |w| "loc=#{w.lat},#{w.lon}" }
params = (locs + options.to_param).join('&')
params = nil if params==""
- uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?')
- @query = uri.to_s
- Timeout.timeout(OSRM_TIMEOUT) do
- Net::HTTP.get_response uri
+
+ if params == nil
+ uri = generate_request_url (path)
+ else
+ uri = generate_request_url (path + '?' + params)
end
-rescue Errno::ECONNREFUSED => e
- raise "*** osrm-routed is not running."
-rescue Timeout::Error
- raise "*** osrm-routed did not respond."
+ response = send_request uri, waypoints, options
end
def request_url path
diff --git a/features/testbot/ferry.feature b/features/testbot/ferry.feature
index 5516061..21cefcb 100644
--- a/features/testbot/ferry.feature
+++ b/features/testbot/ferry.feature
@@ -173,3 +173,33 @@ Feature: Testbot - Handle ferry routes
| from | to | route | time |
| a | g | abcdefg | 23400s +-2 |
| g | a | abcdefg | 23400s +-2 |
+
+ @todo
+ Scenario: Testbot - Ferry duration formats
+ Given the node map
+ | a | c | e | g | i | k | m | o | q | s |
+ | b | d | f | h | j | l | n | p | r | t |
+
+ And the ways
+ | nodes | route | duration |
+ | ab | ferry | 0:01 |
+ | cd | ferry | 00:01 |
+ | ef | ferry | 1:00 |
+ | gh | ferry | 01:00 |
+ | ij | ferry | 02:20 |
+ | kl | ferry | 10:00 |
+ | mn | ferry | 100:00 |
+ | op | ferry | 1000:00 |
+ | qr | ferry | 10000:00 |
+
+ When I route I should get
+ | from | to | route | time |
+ | a | b | ab | 60s +-1 |
+ | c | d | cd | 60s +-1 |
+ | e | f | ef | 3600s +-1 |
+ | g | h | gh | 3600s +-1 |
+ | i | j | ij | 8400s +-1 |
+ | k | l | kl | 36000s +-1 |
+ | m | n | mn | 360000s +-1 |
+ | o | p | mn | 3600000s +-1 |
+ | q | r | mn | 36000000s +-1 |
diff --git a/features/testbot/loop.feature b/features/testbot/loop.feature
index 72cad33..c69e7a2 100644
--- a/features/testbot/loop.feature
+++ b/features/testbot/loop.feature
@@ -4,6 +4,25 @@ Feature: Avoid weird loops caused by rounding errors
Background:
Given the profile "testbot"
+ Scenario: Weired sidestreet loops
+ Given the node map
+ | a | 1 | b | 2 | c | 3 | d |
+ | | | | | | | |
+ | e | | f | | g | | h |
+
+ And the ways
+ | nodes |
+ | aefghd |
+ | abcd |
+ | bf |
+ | cg |
+
+ When I route I should get
+ | waypoints | route | turns |
+ | a,1,d | abcd,abcd | head,via,destination |
+ | a,2,d | abcd,abcd | head,via,destination |
+ | a,3,d | abcd,abcd | head,via,destination |
+
Scenario: Avoid weird loops 1
Given the node locations
| node | lat | lon |
diff --git a/features/testbot/post.feature b/features/testbot/post.feature
new file mode 100644
index 0000000..ff22824
--- /dev/null
+++ b/features/testbot/post.feature
@@ -0,0 +1,100 @@
+ at post @testbot
+Feature: POST request
+
+ Background:
+ Given the profile "testbot"
+ And the HTTP method "POST"
+
+ Scenario: Testbot - viaroute POST request
+ Given the node locations
+ | node | lat | lon |
+ | a | 55.68740 | 12.52430 |
+ | b | 55.68745 | 12.52409 |
+ | c | 55.68711 | 12.52383 |
+ | x | -55.68740 | 12.52430 |
+ | y | -55.68745 | 12.52409 |
+ | z | -55.68711 | 12.52383 |
+
+ And the ways
+ | nodes |
+ | ab |
+ | bc |
+ | xy |
+ | yz |
+
+ When I route I should get
+ | from | to | route | turns |
+ | a | c | ab,bc | head,left,destination |
+ | c | a | bc,ab | head,right,destination |
+ | x | z | xy,yz | head,right,destination |
+ | z | x | yz,xy | head,left,destination |
+
+ Scenario: Testbot - match POST request
+ Given the node map
+ | a | b | c | d |
+ | e | f | g | h |
+
+ And the ways
+ | nodes | oneway |
+ | abcd | yes |
+ | hgfe | yes |
+
+ When I match I should get
+ | trace | matchings |
+ | dcba | hgfe |
+
+ Scenario: Testbot - table POST request
+ Given the node map
+ | x | a | b | y |
+ | | d | e | |
+
+ And the ways
+ | nodes | oneway |
+ | abeda | yes |
+ | xa | |
+ | by | |
+
+ When I request a travel time matrix I should get
+ | | x | y | d | e |
+ | x | 0 | 300 | 400 | 300 |
+ | y | 500 | 0 | 300 | 200 |
+ | d | 200 | 300 | 0 | 300 |
+ | e | 300 | 400 | 100 | 0 |
+
+ Scenario: Testbot - locate POST request
+ Given the node locations
+ | node | lat | lon |
+ | a | -85 | -180 |
+ | b | 0 | 0 |
+ | c | 85 | 180 |
+ | x | -84 | -180 |
+ | y | 84 | 180 |
+
+ And the ways
+ | nodes |
+ | abc |
+
+ When I request locate I should get
+ | in | out |
+ | x | a |
+ | y | c |
+
+ Scenario: Testbot - nearest POST request
+ Given the node locations
+ | node | lat | lon |
+ | a | -85 | -180 |
+ | b | -85 | -160 |
+ | c | -85 | -140 |
+ | x | -84.999 | -180 |
+ | y | -84.999 | -160 |
+ | z | -84.999 | -140 |
+
+ And the ways
+ | nodes |
+ | abc |
+
+ When I request nearest I should get
+ | in | out |
+ | x | a |
+ | y | b |
+ | z | c |
diff --git a/features/testbot/snap.feature b/features/testbot/snap.feature
index bee75bc..01c590b 100644
--- a/features/testbot/snap.feature
+++ b/features/testbot/snap.feature
@@ -98,30 +98,26 @@ Feature: Snap start/end point to the nearest way
| b | x | xb |
| c | x | xc |
- Scenario: Find edges within 1km, and the same from 10km
- Given a grid size of 1000 meters
+ Scenario: Find edges within 100m, and the same from 1km
+ Given a grid size of 100 meters
Given the node map
- | p | | | | | | | | | | | i | | | | | | | | | | | j |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | 8 | | 1 | | 2 | | | | | | | | | |
- | | | | | | | | | | | h | a | b | | | | | | | | | | |
- | o | | | | | | | | | 7 | g | x | c | 3 | | | | | | | | | k |
- | | | | | | | | | | | f | e | d | | | | | | | | | | |
- | | | | | | | | | | 6 | | 5 | | 4 | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | | | | | | | | | | | | | | | | | | | | | | | |
- | n | | | | | | | | | | | m | | | | | | | | | | | l |
+ | p | | | | | | | | i | | | | | | | | j |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | 8 | | 1 | | 2 | | | | | | |
+ | | | | | | | | h | a | b | | | | | | | |
+ | o | | | | | | 7 | g | x | c | 3 | | | | | | k |
+ | | | | | | | | f | e | d | | | | | | | |
+ | | | | | | | 6 | | 5 | | 4 | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | | | | | | | | | | | | | | | | | |
+ | n | | | | | | | | m | | | | | | | | l |
Given the ways
| nodes |
diff --git a/features/testbot/via.feature b/features/testbot/via.feature
index 9eb8f55..a70ee9f 100644
--- a/features/testbot/via.feature
+++ b/features/testbot/via.feature
@@ -52,6 +52,21 @@ Feature: Via points
| a,c,f | ab,bcd,bcd,de,efg |
| a,c,f,h | ab,bcd,bcd,de,efg,efg,gh |
+ Scenario: Duplicate via point
+ Given the node map
+ | x | | | | | |
+ | a | 1 | 2 | 3 | 4 | b |
+ | | | | | | |
+
+ And the ways
+ | nodes |
+ | xa |
+ | ab |
+
+ When I route I should get
+ | waypoints | route | turns |
+ | 1,1,4 | ab,ab | head,via,destination |
+
Scenario: Via points on ring of oneways
# xa it to avoid only having a single ring, which cna trigger edge cases
Given the node map
@@ -77,7 +92,6 @@ Feature: Via points
| 1,3,2 | ab,bc,cd,cd,de,ef,fa,ab,bc | 1600m +-1 | head,straight,straight,via,right,right,right,right,straight,destination |
| 3,2,1 | cd,de,ef,fa,ab,bc,bc,cd,de,ef,fa,ab | 2400m +-1 | head,right,right,right,right,straight,via,straight,right,right,right,right,destination |
- @bug
Scenario: Via points on ring on the same oneway
# xa it to avoid only having a single ring, which cna trigger edge cases
Given the node map
@@ -97,6 +111,6 @@ Feature: Via points
| waypoints | route | distance | turns |
| 1,3 | ab | 200m +-1 | head,destination |
| 3,1 | ab,bc,cd,da,ab | 800m +-1 | head,right,right,right,right,destination |
- | 1,2,3 | ab | 200m +-1 | head,destination |
- | 1,3,2 | ab,bc,cd,da,ab | 1100m +-1 | head,right,right,right,right,destination |
- | 3,2,1 | ab,bc,cd,da,ab,bc,cd,da,ab | 1600m +-1 | head,right,right,right,right,right,right,right,right,destination |
+ | 1,2,3 | ab,ab | 200m +-1 | head,via,destination |
+ | 1,3,2 | ab,ab,bc,cd,da,ab | 1100m +-1 | head,via,right,right,right,right,destination |
+ | 3,2,1 | ab,bc,cd,da,ab,ab,bc,cd,da,ab | 1800m | head,right,right,right,right,via,right,right,right,right,destination |
diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp
index 9babbd7..bc413d7 100644
--- a/include/osrm/route_parameters.hpp
+++ b/include/osrm/route_parameters.hpp
@@ -78,6 +78,8 @@ struct RouteParameters
void setCompressionFlag(const bool flag);
void addCoordinate(const boost::fusion::vector<double, double> &received_coordinates);
+
+ void getCoordinatesFromGeometry(const std::string geometry_string);
short zoom_level;
bool print_instructions;
diff --git a/prepare.cpp b/prepare.cpp
index af10df0..5de3204 100644
--- a/prepare.cpp
+++ b/prepare.cpp
@@ -26,10 +26,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "contractor/processing_chain.hpp"
+#include "contractor/contractor_options.hpp"
#include "util/simple_logger.hpp"
#include <boost/program_options/errors.hpp>
+#include <tbb/task_scheduler_init.h>
+
#include <exception>
#include <ostream>
@@ -37,21 +40,64 @@ int main(int argc, char *argv[])
{
try
{
- return Prepare().Process(argc, argv);
- }
- catch (boost::program_options::too_many_positional_options_error &)
- {
- SimpleLogger().Write(logWARNING) << "Only one file can be specified";
- return 1;
- }
- catch (boost::program_options::error &e)
- {
- SimpleLogger().Write(logWARNING) << e.what();
- return 1;
+ LogPolicy::GetInstance().Unmute();
+ ContractorConfig contractor_config;
+
+ const return_code result = ContractorOptions::ParseArguments(argc, argv, contractor_config);
+
+ if (return_code::fail == result)
+ {
+ return 1;
+ }
+
+ if (return_code::exit == result)
+ {
+ return 0;
+ }
+
+ ContractorOptions::GenerateOutputFilesNames(contractor_config);
+
+ if (1 > contractor_config.requested_num_threads)
+ {
+ SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
+ return 1;
+ }
+
+ const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
+
+ if (recommended_num_threads != contractor_config.requested_num_threads)
+ {
+ SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
+ << recommended_num_threads
+ << "! This setting may have performance side-effects.";
+ }
+
+ if (!boost::filesystem::is_regular_file(contractor_config.osrm_input_path))
+ {
+ SimpleLogger().Write(logWARNING)
+ << "Input file " << contractor_config.osrm_input_path.string() << " not found!";
+ return 1;
+ }
+
+ if (!boost::filesystem::is_regular_file(contractor_config.profile_path))
+ {
+ SimpleLogger().Write(logWARNING) << "Profile " << contractor_config.profile_path.string()
+ << " not found!";
+ return 1;
+ }
+
+ SimpleLogger().Write() << "Input file: " << contractor_config.osrm_input_path.filename().string();
+ SimpleLogger().Write() << "Restrictions file: " << contractor_config.restrictions_path.filename().string();
+ SimpleLogger().Write() << "Profile: " << contractor_config.profile_path.filename().string();
+ SimpleLogger().Write() << "Threads: " << contractor_config.requested_num_threads;
+
+ tbb::task_scheduler_init init(contractor_config.requested_num_threads);
+
+ return Prepare(contractor_config).Run();
}
catch (const std::exception &e)
{
- SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what() << std::endl;
+ SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
return 1;
}
}
diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua
index 497321c..f236063 100644
--- a/profiles/bicycle.lua
+++ b/profiles/bicycle.lua
@@ -1,19 +1,21 @@
-require("lib/access")
-require("lib/maxspeed")
+-- Bicycle profile
+
+local find_access_tag = require("lib/access").find_access_tag
+local limit = require("lib/maxspeed").limit
-- Begin of globals
barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true }
access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true }
-access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
+access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags_hierachy = { "bicycle", "vehicle", "access" }
cycleway_tags = {["track"]=true,["lane"]=true,["opposite"]=true,["opposite_lane"]=true,["opposite_track"]=true,["share_busway"]=true,["sharrow"]=true,["shared"]=true }
service_tag_restricted = { ["parking_aisle"] = true }
restriction_exception_tags = { "bicycle", "vehicle", "access" }
+unsafe_highway_list = { ["primary"] = true, ["secondary"] = true, ["tertiary"] = true, ["primary_link"] = true, ["secondary_link"] = true, ["tertiary_link"] = true}
-default_speed = 15
-
-walking_speed = 6
+local default_speed = 15
+local walking_speed = 6
bicycle_speeds = {
["cycleway"] = default_speed,
@@ -79,8 +81,7 @@ surface_speeds = {
["unpaved"] = 6,
["fine_gravel"] = 6,
["gravel"] = 6,
- ["fine_gravel"] = 6,
- ["pebbelstone"] = 6,
+ ["pebblestone"] = 6,
["ground"] = 6,
["dirt"] = 6,
["earth"] = 6,
@@ -89,24 +90,27 @@ surface_speeds = {
["sand"] = 3
}
-take_minimum_of_speeds = true
-obey_oneway = true
-obey_bollards = false
-use_restrictions = true
-ignore_areas = true -- future feature
-traffic_signal_penalty = 5
-u_turn_penalty = 20
-use_turn_restrictions = false
-turn_penalty = 60
-turn_bias = 1.4
-
+traffic_signal_penalty = 2
+use_turn_restrictions = false
+
+local obey_oneway = true
+local obey_bollards = false
+local ignore_areas = true
+local u_turn_penalty = 20
+local turn_penalty = 60
+local turn_bias = 1.4
+-- reduce the driving speed by 30% for unsafe roads
+-- local safety_penalty = 0.7
+local safety_penalty = 1.0
+local use_public_transport = true
+local fallback_names = true
--modes
-mode_normal = 1
-mode_pushing = 2
-mode_ferry = 3
-mode_train = 4
-mode_movable_bridge = 5
+local mode_normal = 1
+local mode_pushing = 2
+local mode_ferry = 3
+local mode_train = 4
+local mode_movable_bridge = 5
local function parse_maxspeed(source)
if not source then
@@ -122,7 +126,6 @@ local function parse_maxspeed(source)
return n
end
-
function get_exceptions(vector)
for i,v in ipairs(restriction_exception_tags) do
vector:Add(v)
@@ -130,29 +133,31 @@ function get_exceptions(vector)
end
function node_function (node, result)
- local barrier = node:get_value_by_key("barrier")
- local access = Access.find_access_tag(node, access_tags_hierachy)
- local traffic_signal = node:get_value_by_key("highway")
-
- -- flag node if it carries a traffic light
- if traffic_signal and traffic_signal == "traffic_signals" then
- result.traffic_lights = true
- end
-
- -- parse access and barrier tags
- if access and access ~= "" then
- if access_tag_blacklist[access] then
- result.barrier = true
- else
- result.barrier = false
- end
- elseif barrier and barrier ~= "" then
- if barrier_whitelist[barrier] then
- result.barrier = false
- else
- result.barrier = true
- end
- end
+ -- parse access and barrier tags
+ local highway = node:get_value_by_key("highway")
+ local is_crossing = highway and highway == "crossing"
+
+ local access = find_access_tag(node, access_tags_hierachy)
+ if access and access ~= "" then
+ -- access restrictions on crossing nodes are not relevant for
+ -- the traffic on the road
+ if access_tag_blacklist[access] and not is_crossing then
+ result.barrier = true
+ end
+ else
+ local barrier = node:get_value_by_key("barrier")
+ if barrier and "" ~= barrier then
+ if not barrier_whitelist[barrier] then
+ result.barrier = true
+ end
+ end
+ end
+
+ -- check if node is a traffic light
+ local tag = node:get_value_by_key("highway")
+ if tag and "traffic_signals" == tag then
+ result.traffic_lights = true;
+ end
end
function way_function (way, result)
@@ -165,8 +170,8 @@ function way_function (way, result)
local public_transport = way:get_value_by_key("public_transport")
local bridge = way:get_value_by_key("bridge")
if (not highway or highway == '') and
- (not route or route == '') and
- (not railway or railway=='') and
+ (not use_public_transport or not route or route == '') and
+ (not use_public_transport or not railway or railway=='') and
(not amenity or amenity=='') and
(not man_made or man_made=='') and
(not public_transport or public_transport=='') and
@@ -181,7 +186,7 @@ function way_function (way, result)
end
-- access
- local access = Access.find_access_tag(way, access_tags_hierachy)
+ local access = find_access_tag(way, access_tags_hierachy)
if access and access_tag_blacklist[access] then
return
end
@@ -213,7 +218,8 @@ function way_function (way, result)
result.name = ref
elseif name and "" ~= name then
result.name = name
- elseif highway then
+ -- TODO find a better solution for encoding way type
+ elseif fallback_names and highway then
-- if no name exists, use way type
-- this encoding scheme is excepted to be a temporary solution
result.name = "{highway:"..highway.."}"
@@ -246,15 +252,16 @@ function way_function (way, result)
result.forward_speed = route_speeds[route]
result.backward_speed = route_speeds[route]
end
- elseif railway and platform_speeds[railway] then
+ -- public transport
+ elseif use_public_transport and railway and platform_speeds[railway] then
-- railway platforms (old tagging scheme)
result.forward_speed = platform_speeds[railway]
result.backward_speed = platform_speeds[railway]
- elseif platform_speeds[public_transport] then
+ elseif use_public_transport and platform_speeds[public_transport] then
-- public_transport platforms (new tagging platform)
result.forward_speed = platform_speeds[public_transport]
result.backward_speed = platform_speeds[public_transport]
- elseif railway and railway_speeds[railway] then
+ elseif use_public_transport and railway and railway_speeds[railway] then
result.forward_mode = mode_train
result.backward_mode = mode_train
-- railways
@@ -270,6 +277,10 @@ function way_function (way, result)
-- regular ways
result.forward_speed = bicycle_speeds[highway]
result.backward_speed = bicycle_speeds[highway]
+ if safety_penalty < 1 and unsafe_highway_list[highway] then
+ result.forward_speed = result.forward_speed * safety_penalty
+ result.backward_speed = result.backward_speed * safety_penalty
+ end
elseif access and access_tag_whitelist[access] then
-- unknown way, but valid access tag
result.forward_speed = default_speed
@@ -391,7 +402,7 @@ function way_function (way, result)
end
-- maxspeed
- MaxSpeed.limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
+ limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
end
function turn_function (angle)
diff --git a/profiles/car.lua b/profiles/car.lua
index 813afd1..8c68bc9 100644
--- a/profiles/car.lua
+++ b/profiles/car.lua
@@ -1,6 +1,8 @@
--- Begin of globals
---require("lib/access") --function temporarily inlined
+-- Car profile
+
+local find_access_tag = require("lib/access").find_access_tag
+-- Begin of globals
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["lift_gate"] = true, ["no"] = true, ["entrance"] = true }
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true, ["psv"] = true }
@@ -130,10 +132,9 @@ maxspeed_table = {
traffic_signal_penalty = 2
use_turn_restrictions = true
-local take_minimum_of_speeds = false
local obey_oneway = true
local obey_bollards = true
-local ignore_areas = true -- future feature
+local ignore_areas = true
local u_turn_penalty = 20
local abs = math.abs
@@ -147,16 +148,6 @@ local mode_normal = 1
local mode_ferry = 2
local mode_movable_bridge = 3
-local function find_access_tag(source, access_tags_hierachy)
- for i,v in ipairs(access_tags_hierachy) do
- local access_tag = source:get_value_by_key(v)
- if access_tag and "" ~= access_tag then
- return access_tag
- end
- end
- return ""
-end
-
function get_exceptions(vector)
for i,v in ipairs(restriction_exception_tags) do
vector:Add(v)
@@ -187,6 +178,7 @@ local function parse_maxspeed(source)
return n
end
+-- FIXME Why was this commented out?
-- function turn_function (angle)
-- -- print ("called at angle " .. angle )
-- local index = math.abs(math.floor(angle/10+0.5))+1 -- +1 'coz LUA starts as idx 1
@@ -198,7 +190,7 @@ end
function node_function (node, result)
-- parse access and barrier tags
local access = find_access_tag(node, access_tags_hierachy)
- if access ~= "" then
+ if access and access ~= "" then
if access_tag_blacklist[access] then
result.barrier = true
end
@@ -249,12 +241,6 @@ function way_function (way, result)
return
end
- local width = math.huge
- local width_string = way:get_value_by_key("width")
- if width_string and tonumber(width_string:match("%d*")) then
- width = tonumber(width_string:match("%d*"))
- end
-
-- Check if we are allowed to access the way
local access = find_access_tag(way, access_tags_hierachy)
if access_tag_blacklist[access] then
@@ -353,9 +339,14 @@ function way_function (way, result)
local service = way:get_value_by_key("service")
-- Set the name that will be used for instructions
- if ref and "" ~= ref then
+ local has_ref = ref and "" ~= ref
+ local has_name = name and "" ~= name
+
+ if has_name and has_ref then
+ result.name = name .. " (" .. ref .. ")"
+ elseif has_ref then
result.name = ref
- elseif name and "" ~= name then
+ elseif has_name then
result.name = name
-- else
-- result.name = highway -- if no name exists, use way type
@@ -407,12 +398,25 @@ function way_function (way, result)
result.ignore_in_grid = true
end
+ local width = math.huge
+ local lanes = math.huge
+ if result.forward_speed > 0 or result.backward_speed > 0 then
+ local width_string = way:get_value_by_key("width")
+ if width_string and tonumber(width_string:match("%d*")) then
+ width = tonumber(width_string:match("%d*"))
+ end
+
+ local lanes_string = way:get_value_by_key("lanes")
+ if lanes_string and tonumber(lanes_string:match("%d*")) then
+ lanes = tonumber(lanes_string:match("%d*"))
+ end
+ end
-- scale speeds to get better avg driving times
if result.forward_speed > 0 then
local scaled_speed = result.forward_speed*speed_reduction + 11;
local penalized_speed = math.huge
- if width <= 3 then
+ if width <= 3 or lanes <= 1 then
penalized_speed = result.forward_speed / 2;
end
result.forward_speed = math.min(penalized_speed, scaled_speed)
@@ -421,16 +425,10 @@ function way_function (way, result)
if result.backward_speed > 0 then
local scaled_speed = result.backward_speed*speed_reduction + 11;
local penalized_speed = math.huge
- if width <= 3 then
+ if width <= 3 or lanes <= 1 then
penalized_speed = result.backward_speed / 2;
end
result.backward_speed = math.min(penalized_speed, scaled_speed)
end
end
--- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT
-function node_vector_function(vector)
- for v in vector.nodes do
- node_function(v)
- end
-end
diff --git a/profiles/foot.lua b/profiles/foot.lua
index 5a37097..4b3bc1c 100644
--- a/profiles/foot.lua
+++ b/profiles/foot.lua
@@ -1,10 +1,11 @@
-- Foot profile
-require("lib/access")
+local find_access_tag = require("lib/access").find_access_tag
+-- Begin of globals
barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true}
access_tag_whitelist = { ["yes"] = true, ["foot"] = true, ["permissive"] = true, ["designated"] = true }
-access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true }
+access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags_hierachy = { "foot", "access" }
service_tag_restricted = { ["parking_aisle"] = true }
@@ -35,32 +36,36 @@ speeds = {
}
route_speeds = {
- ["ferry"] = 5
+ ["ferry"] = 5
}
platform_speeds = {
- ["platform"] = walking_speed
+ ["platform"] = walking_speed
}
amenity_speeds = {
- ["parking"] = walking_speed,
- ["parking_entrance"] = walking_speed
+ ["parking"] = walking_speed,
+ ["parking_entrance"] = walking_speed
}
man_made_speeds = {
- ["pier"] = walking_speed
+ ["pier"] = walking_speed
}
surface_speeds = {
- ["fine_gravel"] = walking_speed*0.75,
- ["gravel"] = walking_speed*0.75,
- ["pebbelstone"] = walking_speed*0.75,
- ["mud"] = walking_speed*0.5,
- ["sand"] = walking_speed*0.5
+ ["fine_gravel"] = walking_speed*0.75,
+ ["gravel"] = walking_speed*0.75,
+ ["pebblestone"] = walking_speed*0.75,
+ ["mud"] = walking_speed*0.5,
+ ["sand"] = walking_speed*0.5
}
-traffic_signal_penalty = 2
-u_turn_penalty = 2
+leisure_speeds = {
+ ["track"] = walking_speed
+}
+
+traffic_signal_penalty = 2
+u_turn_penalty = 2
use_turn_restrictions = false
--modes
@@ -68,144 +73,150 @@ local mode_normal = 1
local mode_ferry = 2
function get_exceptions(vector)
- for i,v in ipairs(restriction_exception_tags) do
- vector:Add(v)
- end
+ for i,v in ipairs(restriction_exception_tags) do
+ vector:Add(v)
+ end
end
function node_function (node, result)
- local barrier = node:get_value_by_key("barrier")
- local access = Access.find_access_tag(node, access_tags_hierachy)
- local traffic_signal = node:get_value_by_key("highway")
-
- -- flag node if it carries a traffic light
- if traffic_signal and traffic_signal == "traffic_signals" then
- result.traffic_light = true
- end
-
- -- parse access and barrier tags
- if access and access ~= "" then
- if access_tag_blacklist[access] then
- result.barrier = true
- else
- result.barrier = false
- end
- elseif barrier and barrier ~= "" then
- if barrier_whitelist[barrier] then
- result.barrier = false
- else
- result.barrier = true
- end
- end
-
- return 1
-end
-
-function way_function (way, result)
- -- initial routability check, filters out buildings, boundaries, etc
- local highway = way:get_value_by_key("highway")
- local route = way:get_value_by_key("route")
- local man_made = way:get_value_by_key("man_made")
- local railway = way:get_value_by_key("railway")
- local amenity = way:get_value_by_key("amenity")
- local public_transport = way:get_value_by_key("public_transport")
- if (not highway or highway == '') and
- (not route or route == '') and
- (not railway or railway=='') and
- (not amenity or amenity=='') and
- (not man_made or man_made=='') and
- (not public_transport or public_transport=='')
- then
- return
- end
+ local barrier = node:get_value_by_key("barrier")
+ local access = find_access_tag(node, access_tags_hierachy)
+ local traffic_signal = node:get_value_by_key("highway")
- -- don't route on ways that are still under construction
- if highway=='construction' then
- return
- end
+ -- flag node if it carries a traffic light
+ if traffic_signal and traffic_signal == "traffic_signals" then
+ result.traffic_light = true
+ end
- -- access
- local access = Access.find_access_tag(way, access_tags_hierachy)
+ -- parse access and barrier tags
+ if access and access ~= "" then
if access_tag_blacklist[access] then
- return
+ result.barrier = true
+ else
+ result.barrier = false
+ end
+ elseif barrier and barrier ~= "" then
+ if barrier_whitelist[barrier] then
+ result.barrier = false
+ else
+ result.barrier = true
end
+ end
- local name = way:get_value_by_key("name")
- local ref = way:get_value_by_key("ref")
- local junction = way:get_value_by_key("junction")
- local onewayClass = way:get_value_by_key("oneway:foot")
- local duration = way:get_value_by_key("duration")
- local service = way:get_value_by_key("service")
- local area = way:get_value_by_key("area")
- local foot = way:get_value_by_key("foot")
- local surface = way:get_value_by_key("surface")
-
- -- name
- if ref and "" ~= ref and name and "" ~= name then
- result.name = name .. ' / ' .. ref
+ return 1
+end
+
+function way_function (way, result)
+ -- initial routability check, filters out buildings, boundaries, etc
+ local highway = way:get_value_by_key("highway")
+ local leisure = way:get_value_by_key("leisure")
+ local route = way:get_value_by_key("route")
+ local man_made = way:get_value_by_key("man_made")
+ local railway = way:get_value_by_key("railway")
+ local amenity = way:get_value_by_key("amenity")
+ local public_transport = way:get_value_by_key("public_transport")
+ if (not highway or highway == '') and
+ (not leisure or leisure == '') and
+ (not route or route == '') and
+ (not railway or railway=='') and
+ (not amenity or amenity=='') and
+ (not man_made or man_made=='') and
+ (not public_transport or public_transport=='')
+ then
+ return
+ end
+
+ -- don't route on ways that are still under construction
+ if highway=='construction' then
+ return
+ end
+
+ -- access
+ local access = find_access_tag(way, access_tags_hierachy)
+ if access_tag_blacklist[access] then
+ return
+ end
+
+ local name = way:get_value_by_key("name")
+ local ref = way:get_value_by_key("ref")
+ local junction = way:get_value_by_key("junction")
+ local onewayClass = way:get_value_by_key("oneway:foot")
+ local duration = way:get_value_by_key("duration")
+ local service = way:get_value_by_key("service")
+ local area = way:get_value_by_key("area")
+ local foot = way:get_value_by_key("foot")
+ local surface = way:get_value_by_key("surface")
+
+ -- name
+ if ref and "" ~= ref and name and "" ~= name then
+ result.name = name .. ' / ' .. ref
elseif ref and "" ~= ref then
- result.name = ref
- elseif name and "" ~= name then
- result.name = name
- elseif highway then
- result.name = "{highway:"..highway.."}" -- if no name exists, use way type
- -- this encoding scheme is excepted to be a temporary solution
- end
+ result.name = ref
+ elseif name and "" ~= name then
+ result.name = name
+ elseif highway then
+ result.name = "{highway:"..highway.."}" -- if no name exists, use way type
+ -- this encoding scheme is excepted to be a temporary solution
+ end
-- roundabouts
- if "roundabout" == junction then
- result.roundabout = true;
- end
+ if "roundabout" == junction then
+ result.roundabout = true;
+ end
-- speed
- if route_speeds[route] then
- -- ferries (doesn't cover routes tagged using relations)
- result.ignore_in_grid = true
- if duration and durationIsValid(duration) then
- result.duration = math.max( 1, parseDuration(duration) )
- else
- result.forward_speed = route_speeds[route]
- result.backward_speed = route_speeds[route]
- end
- result.forward_mode = mode_ferry
- result.backward_mode = mode_ferry
- elseif railway and platform_speeds[railway] then
- -- railway platforms (old tagging scheme)
- result.forward_speed = platform_speeds[railway]
- result.backward_speed = platform_speeds[railway]
- elseif platform_speeds[public_transport] then
- -- public_transport platforms (new tagging platform)
- result.forward_speed = platform_speeds[public_transport]
- result.backward_speed = platform_speeds[public_transport]
- elseif amenity and amenity_speeds[amenity] then
- -- parking areas
- result.forward_speed = amenity_speeds[amenity]
- result.backward_speed = amenity_speeds[amenity]
- elseif speeds[highway] then
- -- regular ways
- result.forward_speed = speeds[highway]
- result.backward_speed = speeds[highway]
- elseif access and access_tag_whitelist[access] then
- -- unknown way, but valid access tag
- result.forward_speed = walking_speed
- result.backward_speed = walking_speed
- end
-
- -- oneway
- if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
- result.backward_mode = 0
- elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
- -- nothing to do
- elseif onewayClass == "-1" then
- result.forward_mode = 0
- end
-
- -- surfaces
- if surface then
- surface_speed = surface_speeds[surface]
- if surface_speed then
- result.forward_speed = math.min(result.forward_speed, surface_speed)
- result.backward_speed = math.min(result.backward_speed, surface_speed)
- end
+ if route_speeds[route] then
+ -- ferries (doesn't cover routes tagged using relations)
+ result.ignore_in_grid = true
+ if duration and durationIsValid(duration) then
+ result.duration = math.max( 1, parseDuration(duration) )
+ else
+ result.forward_speed = route_speeds[route]
+ result.backward_speed = route_speeds[route]
+ end
+ result.forward_mode = mode_ferry
+ result.backward_mode = mode_ferry
+ elseif railway and platform_speeds[railway] then
+ -- railway platforms (old tagging scheme)
+ result.forward_speed = platform_speeds[railway]
+ result.backward_speed = platform_speeds[railway]
+ elseif platform_speeds[public_transport] then
+ -- public_transport platforms (new tagging platform)
+ result.forward_speed = platform_speeds[public_transport]
+ result.backward_speed = platform_speeds[public_transport]
+ elseif amenity and amenity_speeds[amenity] then
+ -- parking areas
+ result.forward_speed = amenity_speeds[amenity]
+ result.backward_speed = amenity_speeds[amenity]
+ elseif leisure and leisure_speeds[leisure] then
+ -- running tracks
+ result.forward_speed = leisure_speeds[leisure]
+ result.backward_speed = leisure_speeds[leisure]
+ elseif speeds[highway] then
+ -- regular ways
+ result.forward_speed = speeds[highway]
+ result.backward_speed = speeds[highway]
+ elseif access and access_tag_whitelist[access] then
+ -- unknown way, but valid access tag
+ result.forward_speed = walking_speed
+ result.backward_speed = walking_speed
+ end
+
+ -- oneway
+ if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then
+ result.backward_mode = 0
+ elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then
+ -- nothing to do
+ elseif onewayClass == "-1" then
+ result.forward_mode = 0
+ end
+
+ -- surfaces
+ if surface then
+ surface_speed = surface_speeds[surface]
+ if surface_speed then
+ result.forward_speed = math.min(result.forward_speed, surface_speed)
+ result.backward_speed = math.min(result.backward_speed, surface_speed)
end
+ end
end
diff --git a/profiles/lib/access.lua b/profiles/lib/access.lua
index 76d2e2c..3fd4ff6 100644
--- a/profiles/lib/access.lua
+++ b/profiles/lib/access.lua
@@ -1,13 +1,15 @@
local ipairs = ipairs
-module "Access"
+local Access = {}
-function find_access_tag(source,access_tags_hierachy)
+function Access.find_access_tag(source,access_tags_hierachy)
for i,v in ipairs(access_tags_hierachy) do
local tag = source:get_value_by_key(v)
if tag and tag ~= '' then
return tag
end
end
- return nil
+ return ""
end
+
+return Access
diff --git a/profiles/lib/maxspeed.lua b/profiles/lib/maxspeed.lua
index aca344a..0dd9b82 100644
--- a/profiles/lib/maxspeed.lua
+++ b/profiles/lib/maxspeed.lua
@@ -1,8 +1,8 @@
local math = math
-module "MaxSpeed"
+local MaxSpeed = {}
-function limit(way,max,maxf,maxb)
+function MaxSpeed.limit(way,max,maxf,maxb)
if maxf and maxf>0 then
way.forward_speed = math.min(way.forward_speed, maxf)
elseif max and max>0 then
@@ -15,3 +15,5 @@ function limit(way,max,maxf,maxb)
way.backward_speed = math.min(way.backward_speed, max)
end
end
+
+return MaxSpeed
diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp
index 1dcc020..327bb32 100644
--- a/routing_algorithms/alternative_path.hpp
+++ b/routing_algorithms/alternative_path.hpp
@@ -103,8 +103,8 @@ class AlternativeRouting final
int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
NodeID middle_node = SPECIAL_NODEID;
const EdgeWeight min_edge_offset =
- std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
- phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
+ std::min(-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
+ -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
{
diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp
index 3dedc2b..eaa6d3c 100644
--- a/routing_algorithms/shortest_path.hpp
+++ b/routing_algorithms/shortest_path.hpp
@@ -93,8 +93,8 @@ class ShortestPathRouting final
const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg &&
uturn_indicators[current_leg - 1];
const EdgeWeight min_edge_offset =
- std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
- phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
+ std::min(-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
+ -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
// insert new starting nodes into forward heap, adjusted by previous distances.
if ((allow_u_turn || search_from_1st_node) &&
@@ -272,11 +272,13 @@ class ShortestPathRouting final
if (start_id_of_leg1 != last_id_of_packed_legs1)
{
packed_legs1 = packed_legs2;
+ distance1 = distance2;
BOOST_ASSERT(start_id_of_leg1 == temporary_packed_leg1.front());
}
else if (start_id_of_leg2 != last_id_of_packed_legs2)
{
packed_legs2 = packed_legs1;
+ distance2 = distance1;
BOOST_ASSERT(start_id_of_leg2 == temporary_packed_leg2.front());
}
}
diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp
index a629cfb..470954f 100644
--- a/server/api_grammar.hpp
+++ b/server/api_grammar.hpp
@@ -42,7 +42,7 @@ template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Ite
*(query) >> -(uturns);
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | timestamp | u | cmp |
language | instruction | geometry | alt_route | old_API | num_results |
- matching_beta | gps_precision | classify));
+ matching_beta | gps_precision | classify | locs));
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >>
qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
@@ -83,17 +83,20 @@ template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Ite
qi::short_[boost::bind(&HandlerT::setGPSPrecision, handler, ::_1)];
classify = (-qi::lit('&')) >> qi::lit("classify") >> '=' >>
qi::bool_[boost::bind(&HandlerT::setClassify, handler, ::_1)];
+ locs = (-qi::lit('&')) >> qi::lit("locs") >> '=' >>
+ stringforPolyline[boost::bind(&HandlerT::getCoordinatesFromGeometry, handler, ::_1)];
string = +(qi::char_("a-zA-Z"));
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') |
(qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z")));
+ stringforPolyline = +(qi::char_("a-zA-Z0-9_.-[]{}@?|\\%~`^"));
}
qi::rule<Iterator> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location,
hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u,
- uturns, old_API, num_results, matching_beta, gps_precision, classify;
+ uturns, old_API, num_results, matching_beta, gps_precision, classify, locs, stringforPolyline;
HandlerT *handler;
};
diff --git a/server/request_parser.cpp b/server/request_parser.cpp
index 584dcbe..502e6e0 100644
--- a/server/request_parser.cpp
+++ b/server/request_parser.cpp
@@ -42,7 +42,8 @@ namespace http
RequestParser::RequestParser()
: state(internal_state::method_start), current_header({"", ""}),
- selected_compression(no_compression)
+ selected_compression(no_compression), is_post_header(false),
+ content_length(0)
{
}
@@ -58,6 +59,11 @@ RequestParser::parse(request ¤t_request, char *begin, char *end)
}
}
osrm::tribool result = osrm::tribool::indeterminate;
+
+ if(state == internal_state::post_request && content_length <= 0)
+ {
+ result = osrm::tribool::yes;
+ }
return std::make_tuple(result, selected_compression);
}
@@ -70,8 +76,39 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input)
{
return osrm::tribool::no;
}
+ if(input == 'P')
+ {
+ state = internal_state::post_O;
+ return osrm::tribool::indeterminate;
+ }
state = internal_state::method;
return osrm::tribool::indeterminate;
+ case internal_state::post_O:
+ if(input == 'O')
+ {
+ state = internal_state::post_S;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::post_S:
+ if(input == 'S')
+ {
+ state = internal_state::post_T;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::post_T:
+ if(input == 'T')
+ {
+ is_post_header = true;
+ state = internal_state::method;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::no;
+ case internal_state::post_request:
+ current_request.uri.push_back(input);
+ --content_length;
+ return osrm::tribool::indeterminate;
case internal_state::method:
if (input == ' ')
{
@@ -204,6 +241,24 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input)
{
current_request.agent = current_header.value;
}
+ if (boost::iequals(current_header.name, "Content-Length"))
+ {
+ try
+ {
+ content_length = std::stoi(current_header.value);
+ }
+ catch (const std::exception &e)
+ {
+ // Ignore the header if the parameter isn't an int
+ }
+ }
+ if (boost::iequals(current_header.name, "Content-Type"))
+ {
+ if (!boost::icontains(current_header.value, "application/x-www-form-urlencoded"))
+ {
+ return osrm::tribool::no;
+ }
+ }
if (input == '\r')
{
@@ -272,7 +327,19 @@ osrm::tribool RequestParser::consume(request ¤t_request, const char input)
return osrm::tribool::indeterminate;
}
return osrm::tribool::no;
- default: // expecting_newline_3
+ case internal_state::expecting_newline_3:
+ if(input == '\n')
+ {
+ if(is_post_header)
+ {
+ current_request.uri.push_back('?');
+ state = internal_state::post_request;
+ return osrm::tribool::indeterminate;
+ }
+ return osrm::tribool::yes;
+ }
+ return osrm::tribool::no;
+ default: // should never be reached
return input == '\n' ? osrm::tribool::yes : osrm::tribool::no;
}
}
diff --git a/server/request_parser.hpp b/server/request_parser.hpp
index 2b6bf69..3724613 100644
--- a/server/request_parser.hpp
+++ b/server/request_parser.hpp
@@ -80,11 +80,17 @@ class RequestParser
space_before_header_value,
header_value,
expecting_newline_2,
- expecting_newline_3
+ expecting_newline_3,
+ post_O,
+ post_S,
+ post_T,
+ post_request
} state;
header current_header;
compression_type selected_compression;
+ bool is_post_header;
+ int content_length;
};
} // namespace http
diff --git a/tools/components.cpp b/tools/components.cpp
index 7ac64f8..660d922 100644
--- a/tools/components.cpp
+++ b/tools/components.cpp
@@ -76,12 +76,68 @@ void DeleteFileIfExists(const std::string &file_name)
}
}
+void LoadRestrictions(const char* path, std::vector<TurnRestriction>& restriction_list)
+{
+ std::ifstream input_stream(path, std::ios::binary);
+ if (!input_stream.is_open())
+ {
+ throw osrm::exception("Cannot open restriction file");
+ }
+ loadRestrictionsFromFile(input_stream, restriction_list);
+}
+
+std::size_t LoadGraph(const char* path,
+ std::vector<QueryNode>& coordinate_list,
+ std::vector<NodeID>& barrier_node_list,
+ std::vector<TarjanEdge>& graph_edge_list)
+{
+ std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary);
+ if (!input_stream.is_open())
+ {
+ throw osrm::exception("Cannot open osrm file");
+ }
+
+ // load graph data
+ std::vector<NodeBasedEdge> edge_list;
+ std::vector<NodeID> traffic_light_node_list;
+
+ auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list,
+ traffic_light_node_list,
+ coordinate_list);
+
+ loadEdgesFromFile(input_stream, edge_list);
+
+ traffic_light_node_list.clear();
+ traffic_light_node_list.shrink_to_fit();
+
+ // Building an node-based graph
+ for (const auto &input_edge : edge_list)
+ {
+ if (input_edge.source == input_edge.target)
+ {
+ continue;
+ }
+
+ if (input_edge.forward)
+ {
+ graph_edge_list.emplace_back(input_edge.source, input_edge.target,
+ (std::max)(input_edge.weight, 1), input_edge.name_id);
+ }
+ if (input_edge.backward)
+ {
+ graph_edge_list.emplace_back(input_edge.target, input_edge.source,
+ (std::max)(input_edge.weight, 1), input_edge.name_id);
+ }
+ }
+
+ return number_of_nodes;
+}
+
int main(int argc, char *argv[])
{
std::vector<QueryNode> coordinate_list;
std::vector<TurnRestriction> restriction_list;
- std::vector<NodeID> bollard_node_list;
- std::vector<NodeID> traffic_lights_list;
+ std::vector<NodeID> barrier_node_list;
LogPolicy::GetInstance().Unmute();
try
@@ -95,83 +151,10 @@ int main(int argc, char *argv[])
}
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
- std::ifstream restriction_ifstream(argv[2], std::ios::binary);
- const FingerPrint fingerprint_orig;
- FingerPrint fingerprint_loaded;
- restriction_ifstream.read(reinterpret_cast<char *>(&fingerprint_loaded),
- sizeof(FingerPrint));
-
- // check fingerprint and warn if necessary
- if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
- {
- SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
- "Reprocess to get rid of this warning.";
- }
-
- if (!restriction_ifstream.good())
- {
- throw osrm::exception("Could not access <osrm-restrictions> files");
- }
- uint32_t usable_restrictions = 0;
- restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
- restriction_list.resize(usable_restrictions);
-
- // load restrictions
- if (usable_restrictions > 0)
- {
- restriction_ifstream.read(reinterpret_cast<char *>(&restriction_list[0]),
- usable_restrictions * sizeof(TurnRestriction));
- }
- restriction_ifstream.close();
-
- std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary);
- if (!input_stream.is_open())
- {
- throw osrm::exception("Cannot open osrm file");
- }
-
- // load graph data
- std::vector<ImportEdge> edge_list;
- const NodeID number_of_nodes =
- readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list,
- traffic_lights_list, &coordinate_list, restriction_list);
- input_stream.close();
- BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
- "size of restriction_list changed");
-
- SimpleLogger().Write() << restriction_list.size() << " restrictions, "
- << bollard_node_list.size() << " bollard nodes, "
- << traffic_lights_list.size() << " traffic lights";
-
- traffic_lights_list.clear();
- traffic_lights_list.shrink_to_fit();
-
- // Building an node-based graph
std::vector<TarjanEdge> graph_edge_list;
-// DeallocatingVector<TarjanEdge> graph_edge_list;
- for (const auto &input_edge : edge_list)
- {
- if (input_edge.source == input_edge.target)
- {
- continue;
- }
-
- if (input_edge.forward)
- {
- graph_edge_list.emplace_back(input_edge.source, input_edge.target,
- (std::max)(input_edge.weight, 1), input_edge.name_id);
- }
- if (input_edge.backward)
- {
- graph_edge_list.emplace_back(input_edge.target, input_edge.source,
- (std::max)(input_edge.weight, 1), input_edge.name_id);
- }
- }
- edge_list.clear();
- edge_list.shrink_to_fit();
- BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(),
- "input edge vector not properly deallocated");
+ auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, graph_edge_list);
+ LoadRestrictions(argv[2], restriction_list);
tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end());
const auto graph = std::make_shared<TarjanGraph>(number_of_nodes, graph_edge_list);
@@ -181,9 +164,8 @@ int main(int argc, char *argv[])
SimpleLogger().Write() << "Starting SCC graph traversal";
RestrictionMap restriction_map(restriction_list);
- auto tarjan = osrm::make_unique<TarjanSCC<TarjanGraph>>(graph,
- restriction_map,
- bollard_node_list);
+ auto tarjan = osrm::make_unique<TarjanSCC<TarjanGraph>>(graph, restriction_map,
+ barrier_node_list);
tarjan->run();
SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components()
<< " many components";
diff --git a/tools/graph_compare.cpp b/tools/graph_compare.cpp
deleted file mode 100644
index 8adc06e..0000000
--- a/tools/graph_compare.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "../data_structures/dynamic_graph.hpp"
-#include "../data_structures/import_edge.hpp"
-#include "../data_structures/query_node.hpp"
-#include "../data_structures/restriction.hpp"
-#include "../data_structures/static_graph.hpp"
-#include "../util/fingerprint.hpp"
-#include "../util/graph_loader.hpp"
-#include "../util/integer_range.hpp"
-#include "../util/make_unique.hpp"
-#include "../util/osrm_exception.hpp"
-#include "../util/simple_logger.hpp"
-
-#include "../typedefs.h"
-
-#include <algorithm>
-#include <fstream>
-
-struct TarjanEdgeData
-{
- TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
- TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {}
- unsigned distance;
- unsigned name_id;
-};
-
-using StaticTestGraph = StaticGraph<TarjanEdgeData>;
-using DynamicTestGraph = StaticGraph<TarjanEdgeData>;
-using StaticEdge = StaticTestGraph::InputEdge;
-using DynamicEdge = DynamicTestGraph::InputEdge;
-
-int main(int argc, char *argv[])
-{
- std::vector<QueryNode> coordinate_list;
- std::vector<TurnRestriction> restriction_list;
- std::vector<NodeID> bollard_node_list;
- std::vector<NodeID> traffic_lights_list;
-
- LogPolicy::GetInstance().Unmute();
- try
- {
- // enable logging
- if (argc < 3)
- {
- SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
- << " <osrm> <osrm.restrictions>";
- return -1;
- }
-
- SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
- std::ifstream restriction_ifstream(argv[2], std::ios::binary);
- const FingerPrint fingerprint_orig;
- FingerPrint fingerprint_loaded;
- restriction_ifstream.read(reinterpret_cast<char *>(&fingerprint_loaded),
- sizeof(FingerPrint));
-
- // check fingerprint and warn if necessary
- if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
- {
- SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
- "Reprocess to get rid of this warning.";
- }
-
- if (!restriction_ifstream.good())
- {
- throw osrm::exception("Could not access <osrm-restrictions> files");
- }
- uint32_t usable_restrictions = 0;
- restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
- restriction_list.resize(usable_restrictions);
-
- // load restrictions
- if (usable_restrictions > 0)
- {
- restriction_ifstream.read(reinterpret_cast<char *>(&restriction_list[0]),
- usable_restrictions * sizeof(TurnRestriction));
- }
- restriction_ifstream.close();
-
- std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary);
- if (!input_stream.is_open())
- {
- throw osrm::exception("Cannot open osrm file");
- }
-
- // load graph data
- std::vector<ImportEdge> edge_list;
- const NodeID number_of_nodes =
- readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list,
- traffic_lights_list, &coordinate_list, restriction_list);
- input_stream.close();
-
- BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
- "size of restriction_list changed");
-
- SimpleLogger().Write() << restriction_list.size() << " restrictions, "
- << bollard_node_list.size() << " bollard nodes, "
- << traffic_lights_list.size() << " traffic lights";
-
- traffic_lights_list.clear();
- traffic_lights_list.shrink_to_fit();
-
- // Building an node-based graph
- std::vector<StaticEdge> static_graph_edge_list;
- std::vector<DynamicEdge> dynamic_graph_edge_list;
- for (const auto &input_edge : edge_list)
- {
- if (input_edge.source == input_edge.target)
- {
- continue;
- }
-
- if (input_edge.forward)
- {
- static_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
- (std::max)(input_edge.weight, 1),
- input_edge.name_id);
- dynamic_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
- (std::max)(input_edge.weight, 1),
- input_edge.name_id);
- }
- if (input_edge.backward)
- {
- dynamic_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
- (std::max)(input_edge.weight, 1),
- input_edge.name_id);
- static_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
- (std::max)(input_edge.weight, 1),
- input_edge.name_id);
- }
- }
- edge_list.clear();
- edge_list.shrink_to_fit();
- BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(),
- "input edge vector not properly deallocated");
-
- tbb::parallel_sort(static_graph_edge_list.begin(), static_graph_edge_list.end());
- tbb::parallel_sort(dynamic_graph_edge_list.begin(), dynamic_graph_edge_list.end());
-
- auto static_graph =
- osrm::make_unique<StaticTestGraph>(number_of_nodes, static_graph_edge_list);
- auto dynamic_graph =
- osrm::make_unique<DynamicTestGraph>(number_of_nodes, dynamic_graph_edge_list);
-
- SimpleLogger().Write() << "Starting static/dynamic graph comparison";
-
- BOOST_ASSERT(static_graph->GetNumberOfNodes() == dynamic_graph->GetNumberOfNodes());
- BOOST_ASSERT(static_graph->GetNumberOfEdges() == dynamic_graph->GetNumberOfEdges());
- for (const auto node : osrm::irange(0u, static_graph->GetNumberOfNodes()))
- {
- const auto static_range = static_graph->GetAdjacentEdgeRange(node);
- const auto dynamic_range = dynamic_graph->GetAdjacentEdgeRange(node);
- SimpleLogger().Write() << "checking node " << node << "/"
- << static_graph->GetNumberOfNodes();
-
- BOOST_ASSERT(static_range.size() == dynamic_range.size());
- const auto static_begin = static_graph->BeginEdges(node);
- const auto dynamic_begin = dynamic_graph->BeginEdges(node);
-
- // check raw interface
- for (const auto i : osrm::irange(0u, static_range.size()))
- {
- const auto static_target = static_graph->GetTarget(static_begin + i);
- const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i);
- BOOST_ASSERT(static_target == dynamic_target);
-
- const auto static_data = static_graph->GetEdgeData(static_begin + i);
- const auto dynamic_data = dynamic_graph->GetEdgeData(dynamic_begin + i);
-
- BOOST_ASSERT(static_data.distance == dynamic_data.distance);
- BOOST_ASSERT(static_data.name_id == dynamic_data.name_id);
- }
-
- // check range interface
- std::vector<EdgeID> static_target_ids, dynamic_target_ids;
- std::vector<TarjanEdgeData> static_edge_data, dynamic_edge_data;
- for (const auto static_id : static_range)
- {
- static_target_ids.push_back(static_graph->GetTarget(static_id));
- static_edge_data.push_back(static_graph->GetEdgeData(static_id));
- }
- for (const auto dynamic_id : dynamic_range)
- {
- dynamic_target_ids.push_back(dynamic_graph->GetTarget(dynamic_id));
- dynamic_edge_data.push_back(dynamic_graph->GetEdgeData(dynamic_id));
- }
- BOOST_ASSERT(static_target_ids.size() == dynamic_target_ids.size());
- BOOST_ASSERT(std::equal(std::begin(static_target_ids), std::end(static_target_ids),
- std::begin(dynamic_target_ids)));
- }
-
- SimpleLogger().Write() << "Graph comparison finished successfully";
- }
- catch (const std::exception &e)
- {
- SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
- }
-
- return 0;
-}
diff --git a/unit_tests/algorithms/duration_parsing.cpp b/unit_tests/algorithms/duration_parsing.cpp
index ec3b819..e3035dc 100644
--- a/unit_tests/algorithms/duration_parsing.cpp
+++ b/unit_tests/algorithms/duration_parsing.cpp
@@ -41,24 +41,24 @@ BOOST_AUTO_TEST_CASE(all_necessary_test)
BOOST_AUTO_TEST_CASE(common_durations_get_translated)
{
- BOOST_CHECK_EQUAL(parseDuration("00:01"), 600);
- BOOST_CHECK_EQUAL(parseDuration("00:01:01"), 610);
- BOOST_CHECK_EQUAL(parseDuration("01:01"), 36600);
+ BOOST_CHECK_EQUAL(parseDuration("00:01"), 60);
+ BOOST_CHECK_EQUAL(parseDuration("00:01:01"), 61);
+ BOOST_CHECK_EQUAL(parseDuration("01:01"), 3660);
// check all combinations of iso duration tokens
- BOOST_CHECK_EQUAL(parseDuration("PT1M1S"), 610);
- BOOST_CHECK_EQUAL(parseDuration("PT1H1S"), 36010);
- BOOST_CHECK_EQUAL(parseDuration("PT15M"), 9000);
- BOOST_CHECK_EQUAL(parseDuration("PT15S"), 150);
- BOOST_CHECK_EQUAL(parseDuration("PT15H"), 540000);
- BOOST_CHECK_EQUAL(parseDuration("PT1H15M"), 45000);
- BOOST_CHECK_EQUAL(parseDuration("PT1H15M1S"), 45010);
+ BOOST_CHECK_EQUAL(parseDuration("PT1M1S"), 61);
+ BOOST_CHECK_EQUAL(parseDuration("PT1H1S"), 3601);
+ BOOST_CHECK_EQUAL(parseDuration("PT15M"), 900);
+ BOOST_CHECK_EQUAL(parseDuration("PT15S"), 15);
+ BOOST_CHECK_EQUAL(parseDuration("PT15H"), 54000);
+ BOOST_CHECK_EQUAL(parseDuration("PT1H15M"), 4500);
+ BOOST_CHECK_EQUAL(parseDuration("PT1H15M1S"), 4501);
}
BOOST_AUTO_TEST_CASE(iso_8601_durations_case_insensitive)
{
- BOOST_CHECK_EQUAL(parseDuration("PT15m"), 9000);
- BOOST_CHECK_EQUAL(parseDuration("PT1h15m"), 45000);
+ BOOST_CHECK_EQUAL(parseDuration("PT15m"), 900);
+ BOOST_CHECK_EQUAL(parseDuration("PT1h15m"), 4500);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/unit_tests/algorithms/geometry_string.cpp b/unit_tests/algorithms/geometry_string.cpp
new file mode 100644
index 0000000..035b321
--- /dev/null
+++ b/unit_tests/algorithms/geometry_string.cpp
@@ -0,0 +1,74 @@
+/*
+
+Copyright (c) 2015, 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.
+
+*/
+
+#include <boost/test/floating_point_comparison.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include "../../algorithms/polyline_compressor.hpp"
+#include "../../data_structures/coordinate_calculation.hpp"
+
+#include <osrm/coordinate.hpp>
+
+#include <cmath>
+#include <vector>
+
+BOOST_AUTO_TEST_CASE(geometry_string)
+{
+ // Polyline string for the 5 coordinates
+ const std::string polyline = "_gjaR_gjaR_pR_ibE_pR_ibE_pR_ibE_pR_ibE";
+ PolylineCompressor pc;
+ std::vector<FixedPointCoordinate> coords = pc.decode_string(polyline);
+
+ // Test coordinates; these would be the coordinates we give the loc parameter,
+ // e.g. loc=10.00,10.0&loc=10.01,10.1...
+ FixedPointCoordinate coord1(10.00 * COORDINATE_PRECISION, 10.0 * COORDINATE_PRECISION);
+ FixedPointCoordinate coord2(10.01 * COORDINATE_PRECISION, 10.1 * COORDINATE_PRECISION);
+ FixedPointCoordinate coord3(10.02 * COORDINATE_PRECISION, 10.2 * COORDINATE_PRECISION);
+ FixedPointCoordinate coord4(10.03 * COORDINATE_PRECISION, 10.3 * COORDINATE_PRECISION);
+ FixedPointCoordinate coord5(10.04 * COORDINATE_PRECISION, 10.4 * COORDINATE_PRECISION);
+
+ // Put the test coordinates into the vector for comparison
+ std::vector<FixedPointCoordinate> cmp_coords;
+ cmp_coords.emplace_back(coord1);
+ cmp_coords.emplace_back(coord2);
+ cmp_coords.emplace_back(coord3);
+ cmp_coords.emplace_back(coord4);
+ cmp_coords.emplace_back(coord5);
+
+ BOOST_CHECK_EQUAL(cmp_coords.size(), coords.size());
+
+ for(unsigned i = 0; i < cmp_coords.size(); ++i)
+ {
+ const double cmp1_lat = coords.at(i).lat;
+ const double cmp2_lat = cmp_coords.at(i).lat;
+ BOOST_CHECK_CLOSE(cmp1_lat, cmp2_lat, 0.0001);
+
+ const double cmp1_lon = coords.at(i).lon;
+ const double cmp2_lon = cmp_coords.at(i).lon;
+ BOOST_CHECK_CLOSE(cmp1_lon, cmp2_lon, 0.0001);
+ }
+}
diff --git a/util/fingerprint.hpp b/util/fingerprint.hpp
index 82eb136..3894fc8 100644
--- a/util/fingerprint.hpp
+++ b/util/fingerprint.hpp
@@ -29,23 +29,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define FINGERPRINT_H
#include <boost/uuid/uuid.hpp>
+#include <type_traits>
// implements a singleton, i.e. there is one and only one conviguration object
class FingerPrint
{
public:
- FingerPrint();
- FingerPrint(const FingerPrint &) = delete;
- ~FingerPrint();
+ static FingerPrint GetValid();
const boost::uuids::uuid &GetFingerPrint() const;
- bool IsMagicNumberOK() const;
+ bool IsMagicNumberOK(const FingerPrint &other) const;
bool TestGraphUtil(const FingerPrint &other) const;
bool TestPrepare(const FingerPrint &other) const;
bool TestRTree(const FingerPrint &other) const;
bool TestQueryObjects(const FingerPrint &other) const;
private:
- const unsigned magic_number;
+ unsigned magic_number;
char md5_prepare[33];
char md5_tree[33];
char md5_graph[33];
@@ -54,6 +53,10 @@ class FingerPrint
// initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
boost::uuids::uuid named_uuid;
bool has_64_bits;
+
};
+static_assert(std::is_trivial<FingerPrint>::value, "FingerPrint needs to be trivial.");
+
+
#endif /* FingerPrint_H */
diff --git a/util/fingerprint_impl.hpp.in b/util/fingerprint_impl.hpp.in
index 9259afd..98bb122 100644
--- a/util/fingerprint_impl.hpp.in
+++ b/util/fingerprint_impl.hpp.in
@@ -40,35 +40,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#cmakedefine MD5GRAPH "${MD5GRAPH}"
#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
-FingerPrint::FingerPrint() : magic_number(1297240911)
+FingerPrint FingerPrint::GetValid()
{
- md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0';
+ FingerPrint fingerprint;
- boost::uuids::name_generator gen(named_uuid);
+ fingerprint.magic_number = 1297240911;
+ fingerprint.md5_prepare[32] = fingerprint.md5_tree[32] = fingerprint.md5_graph[32] = fingerprint.md5_objects[32] = '\0';
+
+ boost::uuids::name_generator gen(fingerprint.named_uuid);
std::string temp_string;
- std::memcpy(md5_prepare, MD5PREPARE, strlen(MD5PREPARE));
- temp_string += md5_prepare;
- std::memcpy(md5_tree, MD5RTREE, 32);
- temp_string += md5_tree;
- std::memcpy(md5_graph, MD5GRAPH, 32);
- temp_string += md5_graph;
- std::memcpy(md5_objects, MD5OBJECTS, 32);
- temp_string += md5_objects;
-
- named_uuid = gen(temp_string);
- has_64_bits = HAS64BITS;
-}
+ std::memcpy(fingerprint.md5_prepare, MD5PREPARE, 32);
+ temp_string += fingerprint.md5_prepare;
+ std::memcpy(fingerprint.md5_tree, MD5RTREE, 32);
+ temp_string += fingerprint.md5_tree;
+ std::memcpy(fingerprint.md5_graph, MD5GRAPH, 32);
+ temp_string += fingerprint.md5_graph;
+ std::memcpy(fingerprint.md5_objects, MD5OBJECTS, 32);
+ temp_string += fingerprint.md5_objects;
-FingerPrint::~FingerPrint() {}
+ fingerprint.named_uuid = gen(temp_string);
+ fingerprint.has_64_bits = HAS64BITS;
+
+ return fingerprint;
+}
const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; }
-bool FingerPrint::IsMagicNumberOK() const { return 1297240911 == magic_number; }
+bool FingerPrint::IsMagicNumberOK(const FingerPrint& other) const { return other.magic_number == magic_number; }
bool FingerPrint::TestGraphUtil(const FingerPrint &other) const
{
- if (!other.IsMagicNumberOK())
+ if (!IsMagicNumberOK(other))
{
throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file");
}
@@ -77,7 +80,7 @@ bool FingerPrint::TestGraphUtil(const FingerPrint &other) const
bool FingerPrint::TestPrepare(const FingerPrint &other) const
{
- if (!other.IsMagicNumberOK())
+ if (!IsMagicNumberOK(other))
{
throw osrm::exception("osrm input file misses magic number. Check or reprocess the file");
}
@@ -86,7 +89,7 @@ bool FingerPrint::TestPrepare(const FingerPrint &other) const
bool FingerPrint::TestRTree(const FingerPrint &other) const
{
- if (!other.IsMagicNumberOK())
+ if (!IsMagicNumberOK(other))
{
throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file");
}
@@ -95,7 +98,7 @@ bool FingerPrint::TestRTree(const FingerPrint &other) const
bool FingerPrint::TestQueryObjects(const FingerPrint &other) const
{
- if (!other.IsMagicNumberOK())
+ if (!IsMagicNumberOK(other))
{
throw osrm::exception("missing magic number. Check or reprocess the file");
}
diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp
index d741334..71bc9e9 100644
--- a/util/graph_loader.hpp
+++ b/util/graph_loader.hpp
@@ -52,243 +52,57 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_map>
#include <vector>
-template <typename EdgeT>
-NodeID read_undirected_osrm_stream(std::istream &input_stream,
- std::vector<EdgeT> &edge_list,
- std::vector<FixedPointCoordinate> &coordinate_list)
+/**
+ * Reads the .restrictions file and loads it to a vector.
+ * The since the restrictions reference nodes using their external node id,
+ * we need to renumber it to the new internal id.
+*/
+unsigned loadRestrictionsFromFile(std::istream& input_stream,
+ std::vector<TurnRestriction>& restriction_list)
{
- const FingerPrint fingerprint_orig;
+ const FingerPrint fingerprint_valid = FingerPrint::GetValid();
FingerPrint fingerprint_loaded;
- input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
-
- if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+ unsigned number_of_usable_restrictions = 0;
+ input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
+ if (!fingerprint_loaded.TestPrepare(fingerprint_valid))
{
- SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
+ SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
- std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
-
- NodeID n;
- input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
- SimpleLogger().Write() << "Importing n = " << n << " nodes ";
-
- ExternalMemoryNode current_node;
- for (NodeID i = 0; i < n; ++i)
+ input_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
+ restriction_list.resize(number_of_usable_restrictions);
+ if (number_of_usable_restrictions > 0)
{
- input_stream.read(reinterpret_cast<char *>(¤t_node), sizeof(ExternalMemoryNode));
- coordinate_list.emplace_back(current_node.lat, current_node.lon);
- ext_to_int_id_map.emplace(current_node.node_id, i);
- // if (current_node.barrier)
- // {
- // barrier_node_list.emplace_back(i);
- // }
- // if (current_node.traffic_lights)
- // {
- // traffic_light_node_list.emplace_back(i);
- // }
+ input_stream.read((char *) restriction_list.data(),
+ number_of_usable_restrictions * sizeof(TurnRestriction));
}
- // tighten vector sizes
- // barrier_node_list.shrink_to_fit();
- // traffic_light_node_list.shrink_to_fit();
-
- // renumber nodes in turn restrictions
- // for (TurnRestriction ¤t_restriction : restriction_list)
- // {
- // auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node);
- // if (internal_id_iter == ext_to_int_id_map.end())
- // {
- // SimpleLogger().Write(logDEBUG) << "Unmapped from node " <<
- // current_restriction.from.node
- // << " of restriction";
- // continue;
- // }
- // current_restriction.from.node = internal_id_iter->second;
-
- // internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node);
- // if (internal_id_iter == ext_to_int_id_map.end())
- // {
- // SimpleLogger().Write(logDEBUG) << "Unmapped via node " <<
- // current_restriction.via.node
- // << " of restriction";
- // continue;
- // }
-
- // current_restriction.via.node = internal_id_iter->second;
-
- // internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node);
- // if (internal_id_iter == ext_to_int_id_map.end())
- // {
- // SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node
- // << " of restriction";
- // continue;
- // }
- // current_restriction.to.node = internal_id_iter->second;
- // }
-
- EdgeWeight weight;
- NodeID source, target;
- unsigned nameID;
- int length;
- short dir; // direction (0 = open, 1 = forward, 2+ = open)
- bool is_roundabout, ignore_in_grid, is_access_restricted, is_split;
- TravelMode travel_mode;
-
- EdgeID m;
- input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
- edge_list.reserve(m);
- SimpleLogger().Write() << " and " << m << " edges ";
-
- for (EdgeID i = 0; i < m; ++i)
- {
- input_stream.read(reinterpret_cast<char *>(&source), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&target), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&length), sizeof(int));
- input_stream.read(reinterpret_cast<char *>(&dir), sizeof(short));
- input_stream.read(reinterpret_cast<char *>(&weight), sizeof(int));
- input_stream.read(reinterpret_cast<char *>(&nameID), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&is_roundabout), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&ignore_in_grid), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&is_access_restricted), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&travel_mode), sizeof(TravelMode));
- input_stream.read(reinterpret_cast<char *>(&is_split), sizeof(bool));
-
- BOOST_ASSERT_MSG(length > 0, "loaded null length edge");
- BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
- BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction");
-
- // bool forward = true;
- // bool backward = true;
- // if (1 == dir)
- // {
- // backward = false;
- // }
- // if (2 == dir)
- // {
- // forward = false;
- // }
-
- // translate the external NodeIDs to internal IDs
- auto internal_id_iter = ext_to_int_id_map.find(source);
- if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end())
- {
-#ifndef NDEBUG
- SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source;
-#endif
- continue;
- }
- source = internal_id_iter->second;
- internal_id_iter = ext_to_int_id_map.find(target);
- if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end())
- {
-#ifndef NDEBUG
- SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target;
-#endif
- continue;
- }
- target = internal_id_iter->second;
- BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID,
- "nonexisting source or target");
-
- if (source > target)
- {
- std::swap(source, target);
- // std::swap(forward, backward);
- }
-
- edge_list.emplace_back(source, target);
- }
- ext_to_int_id_map.clear();
-
- tbb::parallel_sort(edge_list.begin(), edge_list.end());
-
- // for (unsigned i = 1; i < edge_list.size(); ++i)
- // {
- // if ((edge_list[i - 1].target == edge_list[i].target) &&
- // (edge_list[i - 1].source == edge_list[i].source))
- // {
- // const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward)
- // &&
- // (edge_list[i - 1].backward ==
- // edge_list[i].backward);
- // const bool edge_flags_are_superset1 =
- // (edge_list[i - 1].forward && edge_list[i - 1].backward) &&
- // (edge_list[i].forward != edge_list[i].backward);
- // const bool edge_flags_are_superset_2 =
- // (edge_list[i].forward && edge_list[i].backward) &&
- // (edge_list[i - 1].forward != edge_list[i - 1].backward);
-
- // if (edge_flags_equivalent)
- // {
- // edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
- // edge_list[i - 1].source = SPECIAL_NODEID;
- // }
- // else if (edge_flags_are_superset1)
- // {
- // if (edge_list[i - 1].weight <= edge_list[i].weight)
- // {
- // // edge i-1 is smaller and goes in both directions. Throw away the other edge
- // edge_list[i].source = SPECIAL_NODEID;
- // }
- // else
- // {
- // // edge i-1 is open in both directions, but edge i is smaller in one
- // direction.
- // // Close edge i-1 in this direction
- // edge_list[i - 1].forward = !edge_list[i].forward;
- // edge_list[i - 1].backward = !edge_list[i].backward;
- // }
- // }
- // else if (edge_flags_are_superset_2)
- // {
- // if (edge_list[i - 1].weight <= edge_list[i].weight)
- // {
- // // edge i-1 is smaller for one direction. edge i is open in both. close edge
- // i
- // // in the other direction
- // edge_list[i].forward = !edge_list[i - 1].forward;
- // edge_list[i].backward = !edge_list[i - 1].backward;
- // }
- // else
- // {
- // // edge i is smaller and goes in both direction. Throw away edge i-1
- // edge_list[i - 1].source = SPECIAL_NODEID;
- // }
- // }
- // }
- // }
- // const auto new_end_iter =
- // std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge)
- // {
- // return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID;
- // });
- // edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
- // edge_list.shrink_to_fit();
- SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
- return n;
+ return number_of_usable_restrictions;
}
-template <typename EdgeT>
-NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
- std::vector<EdgeT> &edge_list,
- std::vector<NodeID> &barrier_node_list,
- std::vector<NodeID> &traffic_light_node_list,
- std::vector<QueryNode> *int_to_ext_node_id_map,
- std::vector<TurnRestriction> &restriction_list)
+
+/**
+ * Reads the beginning of an .osrm file and produces:
+ * - list of barrier nodes
+ * - list of traffic lights
+ * - nodes indexed by their internal (non-osm) id
+ */
+NodeID loadNodesFromFile(std::istream &input_stream,
+ std::vector<NodeID> &barrier_node_list,
+ std::vector<NodeID> &traffic_light_node_list,
+ std::vector<QueryNode> &node_array)
{
- const FingerPrint fingerprint_orig;
+ const FingerPrint fingerprint_valid = FingerPrint::GetValid();
FingerPrint fingerprint_loaded;
input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
- if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+ if (!fingerprint_loaded.TestPrepare(fingerprint_valid))
{
SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
- std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
-
NodeID n;
input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
@@ -297,9 +111,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
for (NodeID i = 0; i < n; ++i)
{
input_stream.read(reinterpret_cast<char *>(¤t_node), sizeof(ExternalMemoryNode));
- int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon,
- current_node.node_id);
- ext_to_int_id_map.emplace(current_node.node_id, i);
+ node_array.emplace_back(current_node.lat, current_node.lon, current_node.node_id);
if (current_node.barrier)
{
barrier_node_list.emplace_back(i);
@@ -314,175 +126,48 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
barrier_node_list.shrink_to_fit();
traffic_light_node_list.shrink_to_fit();
- // renumber nodes in turn restrictions
- for (TurnRestriction ¤t_restriction : restriction_list)
- {
- auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node
- << " of restriction";
- continue;
- }
- current_restriction.from.node = internal_id_iter->second;
-
- internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node
- << " of restriction";
- continue;
- }
-
- current_restriction.via.node = internal_id_iter->second;
-
- internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node);
- if (internal_id_iter == ext_to_int_id_map.end())
- {
- SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node
- << " of restriction";
- continue;
- }
- current_restriction.to.node = internal_id_iter->second;
- }
-
- EdgeWeight weight;
- NodeID source, target;
- unsigned nameID;
- int length;
- short dir; // direction (0 = open, 1 = forward, 2+ = open)
- bool is_roundabout, ignore_in_grid, is_access_restricted, is_split;
- TravelMode travel_mode;
+ return n;
+}
+/**
+ * Reads a .osrm file and produces the edges.
+ */
+NodeID loadEdgesFromFile(std::istream &input_stream,
+ std::vector<NodeBasedEdge> &edge_list)
+{
EdgeID m;
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
- edge_list.reserve(m);
+ edge_list.resize(m);
SimpleLogger().Write() << " and " << m << " edges ";
- for (EdgeID i = 0; i < m; ++i)
- {
- input_stream.read(reinterpret_cast<char *>(&source), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&target), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&length), sizeof(int));
- input_stream.read(reinterpret_cast<char *>(&dir), sizeof(short));
- input_stream.read(reinterpret_cast<char *>(&weight), sizeof(int));
- input_stream.read(reinterpret_cast<char *>(&nameID), sizeof(unsigned));
- input_stream.read(reinterpret_cast<char *>(&is_roundabout), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&ignore_in_grid), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&is_access_restricted), sizeof(bool));
- input_stream.read(reinterpret_cast<char *>(&travel_mode), sizeof(TravelMode));
- input_stream.read(reinterpret_cast<char *>(&is_split), sizeof(bool));
-
- BOOST_ASSERT_MSG(length > 0, "loaded null length edge");
- BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
- BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction");
-
- bool forward = true;
- bool backward = true;
- if (1 == dir)
- {
- backward = false;
- }
- if (2 == dir)
- {
- forward = false;
- }
+ input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge));
+
+ BOOST_ASSERT(edge_list.size() > 0);
- // translate the external NodeIDs to internal IDs
- auto internal_id_iter = ext_to_int_id_map.find(source);
- if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end())
- {
-#ifndef NDEBUG
- SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source;
-#endif
- continue;
- }
- source = internal_id_iter->second;
- internal_id_iter = ext_to_int_id_map.find(target);
- if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end())
- {
#ifndef NDEBUG
- SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target;
-#endif
- continue;
- }
- target = internal_id_iter->second;
- BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID,
- "nonexisting source or target");
+ SimpleLogger().Write() << "Validating loaded edges...";
+ std::sort(edge_list.begin(), edge_list.end(),
+ [](const NodeBasedEdge& lhs, const NodeBasedEdge& rhs)
+ {
+ return (lhs.source < rhs.source) || (lhs.source == rhs.source && lhs.target < rhs.target);
+ });
+ for (auto i = 1u; i < edge_list.size(); ++i)
+ {
+ const auto& edge = edge_list[i];
+ const auto& prev_edge = edge_list[i-1];
- if (source > target)
- {
- std::swap(source, target);
- std::swap(forward, backward);
- }
+ BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
+ BOOST_ASSERT_MSG(edge.forward, "edge must be oriented in forward direction");
+ BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
- edge_list.emplace_back(source, target, nameID, weight, forward, backward, is_roundabout,
- ignore_in_grid, is_access_restricted, travel_mode, is_split);
+ BOOST_ASSERT_MSG(edge.source != edge.target, "loaded edges contain a loop");
+ BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target, "loaded edges contain a multi edge");
}
- ext_to_int_id_map.clear();
-
- tbb::parallel_sort(edge_list.begin(), edge_list.end());
+#endif
- for (unsigned i = 1; i < edge_list.size(); ++i)
- {
- if ((edge_list[i - 1].target == edge_list[i].target) &&
- (edge_list[i - 1].source == edge_list[i].source))
- {
- const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) &&
- (edge_list[i - 1].backward == edge_list[i].backward);
- const bool edge_flags_are_superset1 =
- (edge_list[i - 1].forward && edge_list[i - 1].backward) &&
- (edge_list[i].forward != edge_list[i].backward);
- const bool edge_flags_are_superset_2 =
- (edge_list[i].forward && edge_list[i].backward) &&
- (edge_list[i - 1].forward != edge_list[i - 1].backward);
-
- if (edge_flags_equivalent)
- {
- edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
- edge_list[i - 1].source = SPECIAL_NODEID;
- }
- else if (edge_flags_are_superset1)
- {
- if (edge_list[i - 1].weight <= edge_list[i].weight)
- {
- // edge i-1 is smaller and goes in both directions. Throw away the other edge
- edge_list[i].source = SPECIAL_NODEID;
- }
- else
- {
- // edge i-1 is open in both directions, but edge i is smaller in one direction.
- // Close edge i-1 in this direction
- edge_list[i - 1].forward = !edge_list[i].forward;
- edge_list[i - 1].backward = !edge_list[i].backward;
- }
- }
- else if (edge_flags_are_superset_2)
- {
- if (edge_list[i - 1].weight <= edge_list[i].weight)
- {
- // edge i-1 is smaller for one direction. edge i is open in both. close edge i
- // in the other direction
- edge_list[i].forward = !edge_list[i - 1].forward;
- edge_list[i].backward = !edge_list[i - 1].backward;
- }
- else
- {
- // edge i is smaller and goes in both direction. Throw away edge i-1
- edge_list[i - 1].source = SPECIAL_NODEID;
- }
- }
- }
- }
- const auto new_end_iter =
- std::remove_if(edge_list.begin(), edge_list.end(), [](const EdgeT &edge)
- {
- return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID;
- });
- edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
- edge_list.shrink_to_fit();
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
- return n;
+
+ return m;
}
template <typename NodeT, typename EdgeT>
@@ -502,9 +187,10 @@ unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
- FingerPrint fingerprint_loaded, fingerprint_orig;
+ const FingerPrint fingerprint_valid = FingerPrint::GetValid();
+ FingerPrint fingerprint_loaded;
hsgr_input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
- if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
+ if (!fingerprint_loaded.TestGraphUtil(fingerprint_valid))
{
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
"Reprocess to get rid of this warning.";
diff --git a/util/iso_8601_duration_parser.hpp b/util/iso_8601_duration_parser.hpp
index 1981c89..3e558ce 100644
--- a/util/iso_8601_duration_parser.hpp
+++ b/util/iso_8601_duration_parser.hpp
@@ -90,7 +90,7 @@ template <typename Iterator> struct iso_8601_grammar : qi::grammar<Iterator>
unsigned get_duration() const
{
- unsigned temp = 10 * (3600 * hours + 60 * minutes + seconds);
+ unsigned temp = (3600 * hours + 60 * minutes + seconds);
if (temp == 0)
{
temp = std::numeric_limits<unsigned>::max();
diff --git a/util/lua_util.hpp b/util/lua_util.hpp
index af6277c..6dbdc8b 100644
--- a/util/lua_util.hpp
+++ b/util/lua_util.hpp
@@ -55,11 +55,10 @@ inline bool lua_function_exists(lua_State *lua_state, const char *name)
// See http://lua-users.org/wiki/PackagePath for details on the package.path syntax.
inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_name)
{
- const boost::filesystem::path profile_path(file_name);
+ boost::filesystem::path profile_path = boost::filesystem::canonical(file_name);
std::string folder = profile_path.parent_path().string();
// TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters
- const std::string lua_code =
- "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path";
+ const std::string lua_code = "package.path = \"" + folder + "/?.lua;\" .. package.path";
luaL_dostring(lua_state, lua_code.c_str());
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osrm.git
More information about the Pkg-grass-devel
mailing list