Merge branch 'develop'
This commit is contained in:
		
						commit
						300d901618
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,3 +1,7 @@
 | 
			
		||||
# pre compiled dependencies #
 | 
			
		||||
#############################
 | 
			
		||||
osrm-deps
 | 
			
		||||
 | 
			
		||||
# Compiled source #
 | 
			
		||||
###################
 | 
			
		||||
*.com
 | 
			
		||||
 | 
			
		||||
@ -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@mapbox.com
 | 
			
		||||
    - patrick@mapbox.com
 | 
			
		||||
  email:
 | 
			
		||||
    on_success: change
 | 
			
		||||
    on_failure: always
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								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
 | 
			
		||||
 | 
			
		||||
or use our free and daily updated online service at
 | 
			
		||||
| 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) |
 | 
			
		||||
 | 
			
		||||
http://map.project-osrm.org
 | 
			
		||||
## 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).
 | 
			
		||||
 | 
			
		||||
To quickly try OSRM use our [free and daily updated online service](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) |
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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_ */
 | 
			
		||||
 | 
			
		||||
@ -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() &&
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								appveyor-build.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								appveyor-build.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
@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
 | 
			
		||||
							
								
								
									
										43
									
								
								appveyor.yml
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								build-local.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								build-local.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
@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%
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								contractor/contractor_options.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								contractor/contractor_options.cpp
									
									
									
									
									
										Normal file
									
								
							@ -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";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								contractor/contractor_options.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								contractor/contractor_options.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef CONTRACTOR_OPTIONS_HPP
 | 
			
		||||
#define CONTRACTOR_OPTIONS_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
enum class return_code : unsigned
 | 
			
		||||
{
 | 
			
		||||
    ok,
 | 
			
		||||
    fail,
 | 
			
		||||
    exit
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ContractorConfig
 | 
			
		||||
{
 | 
			
		||||
    ContractorConfig() noexcept : requested_num_threads(0) {}
 | 
			
		||||
 | 
			
		||||
    boost::filesystem::path config_file_path;
 | 
			
		||||
    boost::filesystem::path osrm_input_path;
 | 
			
		||||
    boost::filesystem::path restrictions_path;
 | 
			
		||||
    boost::filesystem::path profile_path;
 | 
			
		||||
 | 
			
		||||
    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 ContractorOptions
 | 
			
		||||
{
 | 
			
		||||
    static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config);
 | 
			
		||||
 | 
			
		||||
    static void GenerateOutputFilesNames(ContractorConfig &extractor_config);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // EXTRACTOR_OPTIONS_HPP
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            BOOST_ASSERT(!forward_data.forward);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
            BOOST_ASSERT(reverse_data.forward);
 | 
			
		||||
        }
 | 
			
		||||
        if (forward_data.edgeBasedNodeID == SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
            BOOST_ASSERT(!forward_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,
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
    SimpleLogger().Write() << "building r-tree ...";
 | 
			
		||||
    TIMER_START(rtree);
 | 
			
		||||
 | 
			
		||||
    RangebasedCRC32 crc32;
 | 
			
		||||
    if (crc32.using_hardware())
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << "using hardware based CRC32 computation";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << "using software based CRC32 computation";
 | 
			
		||||
    }
 | 
			
		||||
    BuildRTree(*node_based_edge_list, *internal_to_external_node_map);
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    TIMER_STOP(rtree);
 | 
			
		||||
 | 
			
		||||
    WriteNodeMapping();
 | 
			
		||||
    SimpleLogger().Write() << "writing node map ...";
 | 
			
		||||
    WriteNodeMapping(std::move(internal_to_external_node_map));
 | 
			
		||||
 | 
			
		||||
    /***
 | 
			
		||||
     * Contracting the edge-expanded graph
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    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))
 | 
			
		||||
    RangebasedCRC32 crc32;
 | 
			
		||||
    if (crc32.using_hardware())
 | 
			
		||||
    {
 | 
			
		||||
        boost::program_options::store(boost::program_options::parse_config_file<char>(
 | 
			
		||||
                                          temp_config_path.string().c_str(), cmdline_options, true),
 | 
			
		||||
                                      option_variables);
 | 
			
		||||
        SimpleLogger().Write() << "using hardware based CRC32 computation";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << "using software based CRC32 computation";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (option_variables.count("version"))
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << g_GIT_DESCRIPTION;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    const unsigned crc32_value = crc32(*node_based_edge_list);
 | 
			
		||||
    SimpleLogger().Write() << "CRC32: " << crc32_value;
 | 
			
		||||
 | 
			
		||||
    if (option_variables.count("help"))
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << "\n" << visible_options;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boost::program_options::notify(option_variables);
 | 
			
		||||
 | 
			
		||||
    if (!option_variables.count("restrictions"))
 | 
			
		||||
    {
 | 
			
		||||
        restrictions_path = std::string(input_path.string() + ".restrictions");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!option_variables.count("input"))
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write() << "\n" << visible_options;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
    lua_State *lua_state = luaL_newstate();
 | 
			
		||||
    luabind::open(lua_state);
 | 
			
		||||
 | 
			
		||||
    edge_based_graph_factory->Run(edge_out, geometry_filename, lua_state);
 | 
			
		||||
    EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
{
 | 
			
		||||
    SimpleEdgeData() : capacity(0) {}
 | 
			
		||||
    EdgeWeight capacity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
 | 
			
		||||
using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
 | 
			
		||||
 | 
			
		||||
// Factory method to create NodeBasedDynamicGraph from ImportEdges
 | 
			
		||||
inline bool validateNeighborHood(const NodeBasedDynamicGraph& graph, const NodeID source)
 | 
			
		||||
{
 | 
			
		||||
    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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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 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);
 | 
			
		||||
    }
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    BOOST_ASSERT(validateNodeBasedGraph(*graph));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // 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();
 | 
			
		||||
 | 
			
		||||
    auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
 | 
			
		||||
    return graph;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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,19 +690,8 @@ 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
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                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
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
@ -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";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -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,16 +73,72 @@ 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::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);
 | 
			
		||||
@ -94,138 +152,282 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        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())
 | 
			
		||||
void ExtractionContainers::PrepareEdges()
 | 
			
		||||
{
 | 
			
		||||
            if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
 | 
			
		||||
    // 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())
 | 
			
		||||
    {
 | 
			
		||||
                ++way_start_and_end_iterator;
 | 
			
		||||
        if (edge_iterator->result.source < node_iterator->node_id)
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
        // remove loops
 | 
			
		||||
        if (edge_iterator->result.source == edge_iterator->result.target)
 | 
			
		||||
        {
 | 
			
		||||
                ++restrictions_iterator;
 | 
			
		||||
            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;
 | 
			
		||||
 | 
			
		||||
        TIMER_STOP(fix_restriction_starts);
 | 
			
		||||
        std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "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] 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())
 | 
			
		||||
    // 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())
 | 
			
		||||
    {
 | 
			
		||||
            if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
 | 
			
		||||
        // skip all invalid edges
 | 
			
		||||
        if (edge_iterator->result.source == SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
                ++way_start_and_end_iterator;
 | 
			
		||||
            ++edge_iterator;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
            if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
 | 
			
		||||
 | 
			
		||||
        if (edge_iterator->result.target < node_iterator->node_id)
 | 
			
		||||
        {
 | 
			
		||||
                ++restrictions_iterator;
 | 
			
		||||
            edge_iterator->result.target = SPECIAL_NODEID;
 | 
			
		||||
            ++edge_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;
 | 
			
		||||
 | 
			
		||||
            if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
 | 
			
		||||
        if (edge_iterator->result.target > node_iterator->node_id)
 | 
			
		||||
        {
 | 
			
		||||
                restrictions_iterator->restriction.to.node =
 | 
			
		||||
                    way_start_and_end_iterator->first_segment_target_id;
 | 
			
		||||
            ++node_iterator;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
        TIMER_STOP(fix_restriction_ends);
 | 
			
		||||
        std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
 | 
			
		||||
            return -1.0;
 | 
			
		||||
        }(edge_iterator->weight_data);
 | 
			
		||||
 | 
			
		||||
        // 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));
 | 
			
		||||
        auto& edge = edge_iterator->result;
 | 
			
		||||
        edge.weight = std::max(1, static_cast<int>(std::floor(weight + .5)));
 | 
			
		||||
 | 
			
		||||
        for (const auto &restriction_container : restrictions_list)
 | 
			
		||||
        // 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)
 | 
			
		||||
        {
 | 
			
		||||
            if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
 | 
			
		||||
                SPECIAL_NODEID != restriction_container.restriction.to.node)
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
        ++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();)
 | 
			
		||||
    {
 | 
			
		||||
                restrictions_out_stream.write((char *)&(restriction_container.restriction),
 | 
			
		||||
                                              sizeof(TurnRestriction));
 | 
			
		||||
                ++written_restriction_count;
 | 
			
		||||
        // only invalid edges left
 | 
			
		||||
        if (all_edges_list[i].result.source == SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        // skip invalid edges
 | 
			
		||||
        if (all_edges_list[i].result.target == SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned start_idx = i;
 | 
			
		||||
        NodeID source = all_edges_list[i].result.source;
 | 
			
		||||
        NodeID target = all_edges_list[i].result.target;
 | 
			
		||||
 | 
			
		||||
        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 (all_edges_list[i].result.forward && all_edges_list[i].result.weight < min_forward_weight)
 | 
			
		||||
            {
 | 
			
		||||
                min_forward_idx = i;
 | 
			
		||||
            }
 | 
			
		||||
            if (all_edges_list[i].result.backward && all_edges_list[i].result.weight < min_backward_weight)
 | 
			
		||||
            {
 | 
			
		||||
                min_backward_idx = i;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // this also increments the outer loop counter!
 | 
			
		||||
            i++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
            {
 | 
			
		||||
                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 (has_backward)
 | 
			
		||||
            {
 | 
			
		||||
                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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
        // invalidate all unused edges
 | 
			
		||||
        for (unsigned j = start_idx; j < i; j++)
 | 
			
		||||
        {
 | 
			
		||||
            if (j == min_forward_idx || j == min_backward_idx)
 | 
			
		||||
            {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            all_edges_list[j].result.source = SPECIAL_NODEID;
 | 
			
		||||
            all_edges_list[j].result.target = SPECIAL_NODEID;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        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));
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
    auto start_position = file_out_stream.tellp();
 | 
			
		||||
    file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
@ -252,7 +454,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
 | 
			
		||||
        ++node_id_iterator;
 | 
			
		||||
        ++node_iterator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TIMER_STOP(write_nodes);
 | 
			
		||||
    std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
 | 
			
		||||
 | 
			
		||||
@ -261,204 +462,172 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
 | 
			
		||||
    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())
 | 
			
		||||
        {
 | 
			
		||||
            if (edge_iterator->start < node_iterator->node_id)
 | 
			
		||||
            {
 | 
			
		||||
                ++edge_iterator;
 | 
			
		||||
                continue;
 | 
			
		||||
    SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes";
 | 
			
		||||
}
 | 
			
		||||
            if (edge_iterator->start > node_iterator->node_id)
 | 
			
		||||
 | 
			
		||||
void ExtractionContainers::WriteRestrictions(const std::string& path) const
 | 
			
		||||
{
 | 
			
		||||
                node_iterator++;
 | 
			
		||||
    // 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)
 | 
			
		||||
        {
 | 
			
		||||
            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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            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())
 | 
			
		||||
        if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
 | 
			
		||||
        {
 | 
			
		||||
            if (edge_iterator->target < node_iterator->node_id)
 | 
			
		||||
            {
 | 
			
		||||
                ++edge_iterator;
 | 
			
		||||
            SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.from.way;
 | 
			
		||||
            restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
 | 
			
		||||
            ++restrictions_iterator;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
            if (edge_iterator->target > node_iterator->node_id)
 | 
			
		||||
 | 
			
		||||
        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())
 | 
			
		||||
        {
 | 
			
		||||
                ++node_iterator;
 | 
			
		||||
            SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid node: " << restrictions_iterator->restriction.via.node;
 | 
			
		||||
            restrictions_iterator->restriction.via.node = SPECIAL_NODEID;
 | 
			
		||||
            ++restrictions_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())
 | 
			
		||||
 | 
			
		||||
        if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
 | 
			
		||||
        {
 | 
			
		||||
                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)
 | 
			
		||||
            // 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)
 | 
			
		||||
        {
 | 
			
		||||
                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");
 | 
			
		||||
            // 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
                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));
 | 
			
		||||
                }
 | 
			
		||||
    TIMER_STOP(fix_restriction_starts);
 | 
			
		||||
    std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
 | 
			
		||||
 | 
			
		||||
                // 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));
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
                if (edge_iterator->is_split)
 | 
			
		||||
    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())
 | 
			
		||||
    {
 | 
			
		||||
                    file_out_stream.write((char *)&yes, sizeof(bool));
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
        if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
 | 
			
		||||
        {
 | 
			
		||||
                    file_out_stream.write((char *)&no, sizeof(bool));
 | 
			
		||||
            ++way_start_and_end_iterator;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
                ++number_of_used_edges;
 | 
			
		||||
            }
 | 
			
		||||
            ++edge_iterator;
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
        unsigned total_length = 0;
 | 
			
		||||
        std::vector<unsigned> name_lengths;
 | 
			
		||||
        for (const std::string &temp_string : name_list)
 | 
			
		||||
        if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID ||
 | 
			
		||||
            restrictions_iterator->restriction.via.node == SPECIAL_NODEID)
 | 
			
		||||
        {
 | 
			
		||||
            const unsigned string_length =
 | 
			
		||||
                std::min(static_cast<unsigned>(temp_string.length()), 255u);
 | 
			
		||||
            name_lengths.push_back(string_length);
 | 
			
		||||
            total_length += string_length;
 | 
			
		||||
            ++restrictions_iterator;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        RangeTable<> table(name_lengths);
 | 
			
		||||
        name_file_stream << table;
 | 
			
		||||
 | 
			
		||||
        name_file_stream.write((char *)&total_length, sizeof(unsigned));
 | 
			
		||||
        // write all chars consecutively
 | 
			
		||||
        for (const std::string &temp_string : name_list)
 | 
			
		||||
        if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
 | 
			
		||||
        {
 | 
			
		||||
            const unsigned string_length =
 | 
			
		||||
                std::min(static_cast<unsigned>(temp_string.length()), 255u);
 | 
			
		||||
            name_file_stream.write(temp_string.c_str(), string_length);
 | 
			
		||||
            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;
 | 
			
		||||
 | 
			
		||||
        name_file_stream.close();
 | 
			
		||||
        TIMER_STOP(write_name_index);
 | 
			
		||||
        std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
 | 
			
		||||
        // 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;
 | 
			
		||||
 | 
			
		||||
        SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
 | 
			
		||||
                               << number_of_used_edges << " edges";
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception &e)
 | 
			
		||||
        if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
 | 
			
		||||
        {
 | 
			
		||||
        std::cerr << "Caught Execption:" << e.what() << std::endl;
 | 
			
		||||
            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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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))
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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(
 | 
			
		||||
 | 
			
		||||
@ -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");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
        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 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);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    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(); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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     |       |
 | 
			
		||||
 | 
			
		||||
@ -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  |
 | 
			
		||||
 | 
			
		||||
@ -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 |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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 |
 | 
			
		||||
            | a    | c  | My Way,Your Way (A1) |
 | 
			
		||||
 | 
			
		||||
    @todo
 | 
			
		||||
    Scenario: Car - Use way type to describe unnamed ways
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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     |       |
 | 
			
		||||
 | 
			
		||||
@ -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% |
 | 
			
		||||
 | 
			
		||||
@ -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  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -61,10 +61,9 @@ Feature: Locating Nearest node on a Way - pick closest way
 | 
			
		||||
            | a    | -85     | -180 |
 | 
			
		||||
            | b    | -85     | -160 |
 | 
			
		||||
            | c    | -85     | -140 |
 | 
			
		||||
            | x    |  75 | -180 |
 | 
			
		||||
            | y    |  75 | -180 |
 | 
			
		||||
            | v    |   1 |    1 |
 | 
			
		||||
            | w    |  -1 |   -1 |
 | 
			
		||||
            | 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   |
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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|
 | 
			
		||||
 | 
			
		||||
@ -91,6 +91,6 @@ When /^I match I should get$/ do |table|
 | 
			
		||||
      actual << got
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  table.routing_diff! actual
 | 
			
		||||
  table.diff! actual
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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|
 | 
			
		||||
 | 
			
		||||
@ -74,5 +74,5 @@ Then /^routability should be$/ do |table|
 | 
			
		||||
      actual << output_row
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  table.routing_diff! actual
 | 
			
		||||
  table.diff! actual
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -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|
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -4,19 +4,13 @@ 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
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								features/support/http.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								features/support/http.rb
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 |
 | 
			
		||||
 | 
			
		||||
@ -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        |
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								features/testbot/post.feature
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								features/testbot/post.feature
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
			
		||||
@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   |
 | 
			
		||||
@ -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 |
 | 
			
		||||
 | 
			
		||||
@ -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 |
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,8 @@ struct RouteParameters
 | 
			
		||||
 | 
			
		||||
    void addCoordinate(const boost::fusion::vector<double, double> &received_coordinates);
 | 
			
		||||
    
 | 
			
		||||
    void getCoordinatesFromGeometry(const std::string geometry_string);
 | 
			
		||||
 | 
			
		||||
    short zoom_level;
 | 
			
		||||
    bool print_instructions;
 | 
			
		||||
    bool alternate_route;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								prepare.cpp
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								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 &)
 | 
			
		||||
        LogPolicy::GetInstance().Unmute();
 | 
			
		||||
        ContractorConfig contractor_config;
 | 
			
		||||
 | 
			
		||||
        const return_code result = ContractorOptions::ParseArguments(argc, argv, contractor_config);
 | 
			
		||||
 | 
			
		||||
        if (return_code::fail == result)
 | 
			
		||||
        {
 | 
			
		||||
        SimpleLogger().Write(logWARNING) << "Only one file can be specified";
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
    catch (boost::program_options::error &e)
 | 
			
		||||
 | 
			
		||||
        if (return_code::exit == result)
 | 
			
		||||
        {
 | 
			
		||||
        SimpleLogger().Write(logWARNING) << e.what();
 | 
			
		||||
            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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
traffic_signal_penalty          = 2
 | 
			
		||||
use_turn_restrictions           = false
 | 
			
		||||
turn_penalty      = 60
 | 
			
		||||
turn_bias         = 1.4
 | 
			
		||||
 | 
			
		||||
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,28 +133,30 @@ 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
 | 
			
		||||
  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
 | 
			
		||||
		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
 | 
			
		||||
    -- 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
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 }
 | 
			
		||||
@ -54,11 +55,15 @@ man_made_speeds = {
 | 
			
		||||
surface_speeds = {
 | 
			
		||||
  ["fine_gravel"] =   walking_speed*0.75,
 | 
			
		||||
  ["gravel"] =        walking_speed*0.75,
 | 
			
		||||
	["pebbelstone"] =   walking_speed*0.75,
 | 
			
		||||
  ["pebblestone"] =   walking_speed*0.75,
 | 
			
		||||
  ["mud"] =           walking_speed*0.5,
 | 
			
		||||
  ["sand"] =          walking_speed*0.5
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
leisure_speeds = {
 | 
			
		||||
  ["track"] = walking_speed
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
traffic_signal_penalty   = 2
 | 
			
		||||
u_turn_penalty       = 2
 | 
			
		||||
use_turn_restrictions   = false
 | 
			
		||||
@ -75,7 +80,7 @@ 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 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
 | 
			
		||||
@ -104,12 +109,14 @@ 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
 | 
			
		||||
@ -125,7 +132,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_tag_blacklist[access] then
 | 
			
		||||
    return
 | 
			
		||||
  end
 | 
			
		||||
@ -181,6 +188,10 @@ function way_function (way, result)
 | 
			
		||||
    -- 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]
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -76,80 +76,41 @@ void DeleteFileIfExists(const std::string &file_name)
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
void LoadRestrictions(const char* path, std::vector<TurnRestriction>& restriction_list)
 | 
			
		||||
{
 | 
			
		||||
    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
 | 
			
		||||
    std::ifstream input_stream(path, std::ios::binary);
 | 
			
		||||
    if (!input_stream.is_open())
 | 
			
		||||
    {
 | 
			
		||||
        // enable logging
 | 
			
		||||
        if (argc < 3)
 | 
			
		||||
        {
 | 
			
		||||
            SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
 | 
			
		||||
                                             << " <osrm> <osrm.restrictions>";
 | 
			
		||||
            return -1;
 | 
			
		||||
        throw osrm::exception("Cannot open restriction file");
 | 
			
		||||
    }
 | 
			
		||||
    loadRestrictionsFromFile(input_stream, restriction_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        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))
 | 
			
		||||
std::size_t LoadGraph(const char* path,
 | 
			
		||||
                      std::vector<QueryNode>& coordinate_list,
 | 
			
		||||
                      std::vector<NodeID>& barrier_node_list,
 | 
			
		||||
                      std::vector<TarjanEdge>& graph_edge_list)
 | 
			
		||||
{
 | 
			
		||||
            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);
 | 
			
		||||
    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<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();
 | 
			
		||||
    std::vector<NodeBasedEdge> edge_list;
 | 
			
		||||
    std::vector<NodeID> traffic_light_node_list;
 | 
			
		||||
 | 
			
		||||
        BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
 | 
			
		||||
                         "size of restriction_list changed");
 | 
			
		||||
    auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list,
 | 
			
		||||
                                             traffic_light_node_list,
 | 
			
		||||
                                             coordinate_list);
 | 
			
		||||
 | 
			
		||||
        SimpleLogger().Write() << restriction_list.size() << " restrictions, "
 | 
			
		||||
                               << bollard_node_list.size() << " bollard nodes, "
 | 
			
		||||
                               << traffic_lights_list.size() << " traffic lights";
 | 
			
		||||
    loadEdgesFromFile(input_stream, edge_list);
 | 
			
		||||
 | 
			
		||||
        traffic_lights_list.clear();
 | 
			
		||||
        traffic_lights_list.shrink_to_fit();
 | 
			
		||||
    traffic_light_node_list.clear();
 | 
			
		||||
    traffic_light_node_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)
 | 
			
		||||
@ -168,10 +129,32 @@ int main(int argc, char *argv[])
 | 
			
		||||
                                         (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");
 | 
			
		||||
 | 
			
		||||
    return number_of_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    std::vector<QueryNode> coordinate_list;
 | 
			
		||||
    std::vector<TurnRestriction> restriction_list;
 | 
			
		||||
    std::vector<NodeID> barrier_node_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::vector<TarjanEdge> graph_edge_list;
 | 
			
		||||
        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";
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
@ -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()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										74
									
								
								unit_tests/algorithms/geometry_string.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								unit_tests/algorithms/geometry_string.cpp
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    named_uuid = gen(temp_string);
 | 
			
		||||
    has_64_bits = HAS64BITS;
 | 
			
		||||
    fingerprint.named_uuid = gen(temp_string);
 | 
			
		||||
    fingerprint.has_64_bits = HAS64BITS;
 | 
			
		||||
 | 
			
		||||
    return fingerprint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FingerPrint::~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");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
{
 | 
			
		||||
    const FingerPrint fingerprint_orig;
 | 
			
		||||
    FingerPrint fingerprint_loaded;
 | 
			
		||||
    input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
 | 
			
		||||
 | 
			
		||||
    if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
 | 
			
		||||
    {
 | 
			
		||||
        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 ";
 | 
			
		||||
 | 
			
		||||
    ExternalMemoryNode current_node;
 | 
			
		||||
    for (NodeID i = 0; i < n; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
        // }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
/**
 | 
			
		||||
 * 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;
 | 
			
		||||
    unsigned number_of_usable_restrictions = 0;
 | 
			
		||||
    input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
 | 
			
		||||
    if (!fingerprint_loaded.TestPrepare(fingerprint_valid))
 | 
			
		||||
    {
 | 
			
		||||
        SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
 | 
			
		||||
                                            "Reprocess to get rid of this warning.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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((char *) restriction_list.data(),
 | 
			
		||||
                                number_of_usable_restrictions * sizeof(TurnRestriction));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return number_of_usable_restrictions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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_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;
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        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())
 | 
			
		||||
/**
 | 
			
		||||
 * Reads a .osrm file and produces the edges.
 | 
			
		||||
 */
 | 
			
		||||
NodeID loadEdgesFromFile(std::istream &input_stream,
 | 
			
		||||
                         std::vector<NodeBasedEdge> &edge_list)
 | 
			
		||||
{
 | 
			
		||||
            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);
 | 
			
		||||
    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));
 | 
			
		||||
    input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge));
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
    BOOST_ASSERT(edge_list.size() > 0);
 | 
			
		||||
 | 
			
		||||
        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())
 | 
			
		||||
    SimpleLogger().Write() << "Validating loaded edges...";
 | 
			
		||||
    std::sort(edge_list.begin(), edge_list.end(),
 | 
			
		||||
            [](const NodeBasedEdge& lhs, const NodeBasedEdge& rhs)
 | 
			
		||||
            {
 | 
			
		||||
#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, nameID, weight, forward, backward, is_roundabout,
 | 
			
		||||
                               ignore_in_grid, is_access_restricted, travel_mode, is_split);
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
                return (lhs.source < rhs.source) || (lhs.source == rhs.source && lhs.target < rhs.target);
 | 
			
		||||
            });
 | 
			
		||||
    edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
 | 
			
		||||
    edge_list.shrink_to_fit();
 | 
			
		||||
    for (auto i = 1u; i < edge_list.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
        const auto& edge = edge_list[i];
 | 
			
		||||
        const auto& prev_edge = edge_list[i-1];
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    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.";
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user