From ce43b09991d8a3882bead391866a86c7526b820a Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Wed, 19 Dec 2012 15:53:05 +0100 Subject: [PATCH 001/161] support lua require() --- Extractor/ScriptingEnvironment.cpp | 4 +++ Rakefile | 5 ++-- Util/Lua.h | 44 ++++++++++++++++++++++++++++++ createHierarchy.cpp | 6 ++++ features/support/data.rb | 6 ++-- features/support/hash.rb | 28 ++++++++++++------- profiles/bicycle.lua | 18 ++++-------- 7 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 Util/Lua.h diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 01f183166..c91ba1c65 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -27,6 +27,7 @@ extern "C" { #include "ScriptingEnvironment.h" #include "../typedefs.h" #include "../Util/OpenMPWrapper.h" +#include "../Util/Lua.h" ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { @@ -51,6 +52,9 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::def("durationIsValid", durationIsValid), luabind::def("parseDuration", parseDuration) ]; + + luaAddScriptFolderToLoadPath( myLuaState, fileName ); + //#pragma omp critical // { // if(0 != luaL_dostring( diff --git a/Rakefile b/Rakefile index 727412797..2588c4f59 100644 --- a/Rakefile +++ b/Rakefile @@ -7,6 +7,7 @@ require 'sys/proctable' DATA_FOLDER = 'sandbox' PROFILE = 'bicycle' OSRM_PORT = 5000 +PROFILES_FOLDER = '../profiles' Cucumber::Rake::Task.new do |t| t.cucumber_opts = %w{--format pretty} @@ -116,9 +117,9 @@ end desc "Reprocess OSM data." task :process => :setup do Dir.chdir DATA_FOLDER do - raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua" + raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua" puts - raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua" + raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua" puts end end diff --git a/Util/Lua.h b/Util/Lua.h new file mode 100644 index 000000000..f6cfe4720 --- /dev/null +++ b/Util/Lua.h @@ -0,0 +1,44 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef LUA_UTIL_ +#define LUA_UTIL_ + +#include +#include + +bool lua_function_exists(lua_State* lua_state, const char* name) +{ + using namespace luabind; + object g = globals(lua_state); + object func = g[name]; + return func && type(func) == LUA_TFUNCTION; +} + +void luaAddScriptFolderToLoadPath(lua_State* myLuaState, const char* fileName) { + //add the folder contain the script to the lua load path, so script can easily require() other lua scripts inside that folder + //see http://lua-users.org/wiki/PackagePath for details on the package.path syntax + const boost::filesystem::path profilePath( fileName ); + const std::string folder = profilePath.parent_path().c_str(); + const std::string luaCode = "package.path = \"" + folder + "/?.lua;\" .. package.path"; + luaL_dostring(myLuaState,luaCode.c_str()); +} + +#endif /* LUA_UTIL_ */ diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 5d7f13d32..6dfae5d5d 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -47,6 +47,7 @@ extern "C" { #include "Util/InputFileUtil.h" #include "Util/GraphLoader.h" #include "Util/StringUtil.h" +#include "Util/Lua.h" using namespace std; @@ -111,6 +112,11 @@ int main (int argc, char *argv[]) { // Connect LuaBind to this lua state luabind::open(myLuaState); + //open utility libraries string library; + luaL_openlibs(myLuaState); + + //adjust lua load path + luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") ); // Now call our function in a lua script INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") ); diff --git a/features/support/data.rb b/features/support/data.rb index 392265da4..f83bbd223 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -13,7 +13,7 @@ OSM_TIMESTAMP = '2000-00-00T00:00:00Z' DEFAULT_SPEEDPROFILE = 'bicycle' WAY_SPACING = 100 DEFAULT_GRID_SIZE = 100 #meters - +PROFILES_PATH = '../profiles' ORIGIN = [1,1] @@ -205,7 +205,7 @@ def reprocess unless extracted? log_preprocess_info log "== Extracting #{@osm_file}.osm...", :preprocess - unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@profile}.lua" + unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua" log "*** Exited with code #{$?.exitstatus}.", :preprocess raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}." end @@ -214,7 +214,7 @@ def reprocess unless prepared? log_preprocess_info log "== Preparing #{@osm_file}.osm...", :preprocess - unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@profile}.lua" + unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua" log "*** Exited with code #{$?.exitstatus}.", :preprocess raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}." end diff --git a/features/support/hash.rb b/features/support/hash.rb index b4b2f762b..83e5f916d 100644 --- a/features/support/hash.rb +++ b/features/support/hash.rb @@ -1,39 +1,47 @@ require 'digest/sha1' -def hash_of_file path +def hash_of_files paths + paths = [paths] unless paths.is_a? Array hash = Digest::SHA1.new - open(path,'r') do |io| - while !io.eof - buf = io.readpartial 1024 - hash.update buf + for path in paths do + open(path,'r') do |io| + while !io.eof + buf = io.readpartial 1024 + hash.update buf + end end end return hash.hexdigest end + def profile_hash @@profile_hashes ||= {} - @@profile_hashes[@profile] ||= hash_of_file "../profiles/#{@profile}.lua" + @@profile_hashes[@profile] ||= hash_of_files "#{PROFILES_PATH}/#{@profile}.lua" end def osm_hash @osm_hash ||= Digest::SHA1.hexdigest osm_str end +def lua_lib_hash + @lua_lib_hash ||= hash_of_files Dir.glob("../profiles/lib/*.lua") +end + def bin_extract_hash - @@bin_extract_hash ||= hash_of_file '../osrm-extract' + @@bin_extract_hash ||= hash_of_files '../osrm-extract' end def bin_prepare_hash - @@bin_prepare_hash ||= hash_of_file '../osrm-prepare' + @@bin_prepare_hash ||= hash_of_files '../osrm-prepare' end def bin_routed_hash - @@bin_routed_hash ||= hash_of_file '../osrm-routed' + @@bin_routed_hash ||= hash_of_files '../osrm-routed' end #combine state of data, profile and binaries into a hash that identifies the exact test scenario def fingerprint - @fingerprint ||= Digest::SHA1.hexdigest "#{bin_extract_hash}-#{bin_prepare_hash}-#{bin_routed_hash}-#{profile_hash}-#{osm_hash}" + @fingerprint ||= Digest::SHA1.hexdigest "#{bin_extract_hash}-#{bin_prepare_hash}-#{bin_routed_hash}-#{profile_hash}-#{lua_lib_hash}-#{osm_hash}" end diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index c27771b14..f077aa1d6 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,3 +1,5 @@ +require("lib/access") + -- 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} access_tag_whitelist = { ["yes"] = true, ["permissive"] = true, ["designated"] = true } @@ -58,7 +60,6 @@ amenity_speeds = { route_speeds = { ["ferry"] = 5 } - take_minimum_of_speeds = true obey_oneway = true obey_bollards = false @@ -70,19 +71,10 @@ u_turn_penalty = 20 -- End of globals --find first tag in access hierachy which is set -function find_access_tag(source) - for i,v in ipairs(access_tags_hierachy) do - local tag = source.tags:Find(v) - if tag ~= '' then --and tag ~= "" then - return tag - end - end - return nil -end function node_function (node) local barrier = node.tags:Find ("barrier") - local access = find_access_tag(node) + local access = Access.find_access_tag(node, access_tags_hierachy) local traffic_signal = node.tags:Find("highway") -- flag node if it carries a traffic light @@ -91,7 +83,7 @@ function node_function (node) end -- parse access and barrier tags - if access and access ~= "" then + if access and access ~= "" then if access_tag_blacklist[access] then node.bollard = true else @@ -134,7 +126,7 @@ function way_function (way, numberOfNodesInWay) local service = way.tags:Find("service") local area = way.tags:Find("area") local amenity = way.tags:Find("amenity") - local access = find_access_tag(way) + local access = Access.find_access_tag(way, access_tags_hierachy) -- initial routability check, filters out buildings, boundaries, etc if (not highway or highway == '') and From 09e331a76b685d19bb3c6e3cf3abc6e8ddeda3e5 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 20 Dec 2012 22:12:07 +0100 Subject: [PATCH 002/161] fix gitignore to avoid ignoring subfolders. add missing lua file --- .gitignore | 26 +++++++++++++------------- profiles/lib/access.lua | 13 +++++++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 profiles/lib/access.lua diff --git a/.gitignore b/.gitignore index d76967bc1..ccedb3d78 100644 --- a/.gitignore +++ b/.gitignore @@ -54,23 +54,23 @@ stxxl.errlog # compiled protobuffers # ######################### -DataStructures/pbf-proto/*.pb.h -DataStructures/pbf-proto/*.pb.cc +/DataStructures/pbf-proto/*.pb.h +/DataStructures/pbf-proto/*.pb.cc # External Libs # ################# -lib/ -win/lib +/lib/ +/win/lib # Visual Studio Temp + build Files # #################################### -win/*.user -win/*.ncb -win/*.suo -win/Debug/ -win/Release/ -win/bin/ -win/bin-debug/ +/win/*.user +/win/*.ncb +/win/*.suo +/win/Debug/ +/win/Release/ +/win/bin/ +/win/bin-debug/ /osrm-extract /osrm-routed /osrm-prepare @@ -78,6 +78,6 @@ win/bin-debug/ # Sandbox folder # ################### -sandbox/ +/sandbox/ -test/profile.lua \ No newline at end of file +/test/profile.lua \ No newline at end of file diff --git a/profiles/lib/access.lua b/profiles/lib/access.lua new file mode 100644 index 000000000..a1e2fcf4d --- /dev/null +++ b/profiles/lib/access.lua @@ -0,0 +1,13 @@ +local ipairs = ipairs + +module "Access" + +function find_access_tag(source,access_tags_hierachy) + for i,v in ipairs(access_tags_hierachy) do + local tag = source.tags:Find(v) + if tag ~= '' then + return tag + end + end + return nil +end \ No newline at end of file From 28f0782b17bd861add8629186a14b0f58e1b9369 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 28 Dec 2012 22:05:28 +0100 Subject: [PATCH 003/161] code cleanup, merge Lua.h and LuaUtil.h --- Extractor/LuaUtil.h | 35 ------------------------------ Extractor/ScriptingEnvironment.cpp | 2 +- Extractor/ScriptingEnvironment.h | 1 - Util/{Lua.h => LuaUtil.h} | 34 +++++++++++++++++++---------- createHierarchy.cpp | 2 +- 5 files changed, 24 insertions(+), 50 deletions(-) delete mode 100644 Extractor/LuaUtil.h rename Util/{Lua.h => LuaUtil.h} (55%) diff --git a/Extractor/LuaUtil.h b/Extractor/LuaUtil.h deleted file mode 100644 index 7134f96e0..000000000 --- a/Extractor/LuaUtil.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - - - -#ifndef LUAUTIL_H_ -#define LUAUTIL_H_ - -#include - -template -void LUA_print(T number) { - std::cout << "[LUA] " << number << std::endl; -} - - - -#endif /* LUAUTIL_H_ */ diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index c91ba1c65..dbeb2f5f0 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -27,7 +27,7 @@ extern "C" { #include "ScriptingEnvironment.h" #include "../typedefs.h" #include "../Util/OpenMPWrapper.h" -#include "../Util/Lua.h" +#include "../Util/LuaUtil.h" ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { diff --git a/Extractor/ScriptingEnvironment.h b/Extractor/ScriptingEnvironment.h index 05528d408..40f389878 100644 --- a/Extractor/ScriptingEnvironment.h +++ b/Extractor/ScriptingEnvironment.h @@ -30,7 +30,6 @@ extern "C" { #include "ExtractionHelperFunctions.h" #include "ExtractorStructs.h" -#include "LuaUtil.h" #include "../DataStructures/ImportNode.h" diff --git a/Util/Lua.h b/Util/LuaUtil.h similarity index 55% rename from Util/Lua.h rename to Util/LuaUtil.h index f6cfe4720..f47869a8a 100644 --- a/Util/Lua.h +++ b/Util/LuaUtil.h @@ -18,27 +18,37 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ -#ifndef LUA_UTIL_ -#define LUA_UTIL_ + +#ifndef LUAUTIL_H_ +#define LUAUTIL_H_ + +#include #include #include +template +void LUA_print(T number) { + std::cout << "[LUA] " << number << std::endl; +} + +// Check if the lua function is defined bool lua_function_exists(lua_State* lua_state, const char* name) { - using namespace luabind; - object g = globals(lua_state); - object func = g[name]; - return func && type(func) == LUA_TFUNCTION; + luabind::object g = luabind::globals(lua_state); + luabind::object func = g[name]; + return func && (luabind::type(func) == LUA_TFUNCTION); } +// Add the folder contain the script to the lua load path, so script can easily require() other lua scripts inside that folder, or subfolders. +// See http://lua-users.org/wiki/PackagePath for details on the package.path syntax. void luaAddScriptFolderToLoadPath(lua_State* myLuaState, const char* fileName) { - //add the folder contain the script to the lua load path, so script can easily require() other lua scripts inside that folder - //see http://lua-users.org/wiki/PackagePath for details on the package.path syntax const boost::filesystem::path profilePath( fileName ); - const std::string folder = profilePath.parent_path().c_str(); - const std::string luaCode = "package.path = \"" + folder + "/?.lua;\" .. package.path"; - luaL_dostring(myLuaState,luaCode.c_str()); + if( !profilePath.parent_path().empty() ) { + const std::string folder = profilePath.parent_path().string(); + const std::string luaCode = "package.path = \"" + folder + "/?.lua;\" .. package.path"; + luaL_dostring( myLuaState, luaCode.c_str() ); + } } -#endif /* LUA_UTIL_ */ +#endif /* LUAUTIL_H_ */ diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 6dfae5d5d..eb06a8842 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -47,7 +47,7 @@ extern "C" { #include "Util/InputFileUtil.h" #include "Util/GraphLoader.h" #include "Util/StringUtil.h" -#include "Util/Lua.h" +#include "Util/LuaUtil.h" using namespace std; From 943c15927a03450665f26c9bf690a42069681a81 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 29 Dec 2012 14:14:01 +0100 Subject: [PATCH 004/161] Fixing data type issue that prevented large files on windows. See issue #55 --- Contractor/Contractor.h | 2 +- DataStructures/NNGrid.h | 62 ++++++++++---------- Extractor/ExtractionContainers.cpp | 90 +++++++++++++++--------------- typedefs.h | 17 ++++-- 4 files changed, 89 insertions(+), 82 deletions(-) diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index aad4123ac..495b13147 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -274,7 +274,7 @@ public: TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); //Write dummy number of edges to temporary file // std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary); - long initialFilePosition = tempStorage.tell(temporaryStorageSlotID); + uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID); unsigned numberOfTemporaryEdges = 0; tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index f84a0a45f..9f280bc14 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -21,10 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef NNGRID_H_ #define NNGRID_H_ -#include #include #include #include +#include + +#include #include #include #include @@ -58,7 +60,7 @@ template class NNGrid { public: NNGrid() /*: cellCache(500), fileCache(500)*/ { - ramIndexTable.resize((1024*1024), ULONG_MAX); + ramIndexTable.resize((1024*1024), std::numeric_limits::max()); } NNGrid(const char* rif, const char* _i) { @@ -66,7 +68,7 @@ public: ERR("Not available in Write mode"); } iif = std::string(_i); - ramIndexTable.resize((1024*1024), ULONG_MAX); + ramIndexTable.resize((1024*1024), std::numeric_limits::max()); ramInFile.open(rif, std::ios::in | std::ios::binary); if(!ramInFile) { ERR(rif << " not found"); } @@ -87,7 +89,7 @@ public: void OpenIndexFiles() { assert(ramInFile.is_open()); - ramInFile.read(static_cast(static_cast(&ramIndexTable[0]) ), sizeof(unsigned long)*1024*1024); + ramInFile.read(static_cast(static_cast(&ramIndexTable[0]) ), sizeof(uint64_t)*1024*1024); ramInFile.close(); } @@ -114,8 +116,8 @@ public: INFO("finished sorting after " << (get_timestamp() - timestamp) << "s"); std::vector entriesInFileWithRAMSameIndex; unsigned indexInRamTable = entries.begin()->ramIndex; - unsigned long lastPositionInIndexFile = 0; - cout << "writing data ..." << flush; + uint64_t lastPositionInIndexFile = 0; + std::cout << "writing data ..." << std::flush; p.reinit(entries.size()); boost::unordered_map< unsigned, unsigned > cellMap(1024); BOOST_FOREACH(GridEntry & gridEntry, entries) { @@ -143,9 +145,9 @@ public: indexOutFile.close(); //Serialize RAM Index - ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc); + std::ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc); //write 4 MB of index Table in RAM - ramFile.write((char *)&ramIndexTable[0], sizeof(unsigned long)*1024*1024 ); + ramFile.write((char *)&ramIndexTable[0], sizeof(uint64_t)*1024*1024 ); //close ram index file ramFile.close(); } @@ -174,7 +176,7 @@ public: // INFO("looked up " << candidates.size()); _GridEdge smallestEdge; _Coordinate tmp, edgeStartCoord, edgeEndCoord; - double dist = numeric_limits::max(); + double dist = std::numeric_limits::max(); double r, tmpDist; BOOST_FOREACH(_GridEdge candidate, candidates) { @@ -314,13 +316,13 @@ private: return (std::fabs(d1 - d2) < FLT_EPSILON); } - inline unsigned FillCell(std::vector& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) { + inline unsigned FillCell(std::vector& entriesWithSameRAMIndex, const uint64_t fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) { std::vector tmpBuffer(32*32*4096,0); - unsigned long indexIntoTmpBuffer = 0; + uint64_t indexIntoTmpBuffer = 0; unsigned numberOfWrittenBytes = 0; assert(indexOutFile.is_open()); - std::vector cellIndex(32*32,ULONG_MAX); + std::vector cellIndex(32*32,std::numeric_limits::max()); for(unsigned i = 0; i < entriesWithSameRAMIndex.size() -1; ++i) { assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex); @@ -356,8 +358,8 @@ private: indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer); assert(entriesWithSameFileIndex.size() == 0); - indexOutFile.write(static_cast(static_cast(&cellIndex[0])),32*32*sizeof(unsigned long)); - numberOfWrittenBytes += 32*32*sizeof(unsigned long); + indexOutFile.write(static_cast(static_cast(&cellIndex[0])),32*32*sizeof(uint64_t)); + numberOfWrittenBytes += 32*32*sizeof(uint64_t); //write contents of tmpbuffer to disk indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char)); @@ -366,7 +368,7 @@ private: return numberOfWrittenBytes; } - inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector &vectorWithSameFileIndex, std::vector & tmpBuffer, const unsigned long index) const { + inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector &vectorWithSameFileIndex, std::vector & tmpBuffer, const uint64_t index) const { sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() ); vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end()); const unsigned lengthOfBucket = vectorWithSameFileIndex.size(); @@ -394,8 +396,8 @@ private: inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const { unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex); - unsigned long startIndexInFile = ramIndexTable[ramIndex]; - if(startIndexInFile == ULONG_MAX) { + uint64_t startIndexInFile = ramIndexTable[ramIndex]; + if(startIndexInFile == std::numeric_limits::max()) { return; } unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex); @@ -409,14 +411,14 @@ private: } //only read the single necessary cell index - localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(unsigned long))); - unsigned long fetchedIndex = 0; - localStream->read(static_cast( static_cast(&fetchedIndex)), sizeof(unsigned long)); + localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(uint64_t))); + uint64_t fetchedIndex = 0; + localStream->read(static_cast( static_cast(&fetchedIndex)), sizeof(uint64_t)); - if(fetchedIndex == ULONG_MAX) { + if(fetchedIndex == std::numeric_limits::max()) { return; } - const unsigned long position = fetchedIndex + 32*32*sizeof(unsigned long) ; + const uint64_t position = fetchedIndex + 32*32*sizeof(uint64_t) ; unsigned lengthOfBucket; unsigned currentSizeOfResult = result.size(); @@ -428,12 +430,12 @@ private: inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) { unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex); - unsigned long startIndexInFile = ramIndexTable[ramIndex]; - if(startIndexInFile == ULONG_MAX) { + uint64_t startIndexInFile = ramIndexTable[ramIndex]; + if(startIndexInFile == std::numeric_limits::max()) { return; } - unsigned long cellIndex[32*32]; + uint64_t cellIndex[32*32]; cellMap.clear(); BuildCellIndexToFileIndexMap(ramIndex, cellMap); @@ -446,12 +448,12 @@ private: } localStream->seekg(startIndexInFile); - localStream->read(static_cast(static_cast( cellIndex)), 32*32*sizeof(unsigned long)); + localStream->read(static_cast(static_cast( cellIndex)), 32*32*sizeof(uint64_t)); assert(cellMap.find(fileIndex) != cellMap.end()); - if(cellIndex[cellMap[fileIndex]] == ULONG_MAX) { + if(cellIndex[cellMap[fileIndex]] == std::numeric_limits::max()) { return; } - const unsigned long position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(unsigned long) ; + const uint64_t position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(uint64_t) ; unsigned lengthOfBucket; unsigned currentSizeOfResult = result.size(); @@ -574,14 +576,14 @@ private: return ramIndex; } - const static unsigned long END_OF_BUCKET_DELIMITER = UINT_MAX; + const static uint64_t END_OF_BUCKET_DELIMITER = boost::integer_traits::const_max; std::ofstream indexOutFile; std::ifstream ramInFile; #ifndef ROUTED stxxl::vector entries; #endif - std::vector ramIndexTable; //8 MB for first level index in RAM + std::vector ramIndexTable; //8 MB for first level index in RAM std::string iif; // LRUCache > cellCache; // LRUCache > fileCache; diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index b4a2fe060..93a0fd674 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -27,31 +27,31 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const double time = get_timestamp(); boost::uint64_t memory_to_use = static_cast(amountOfRAM) * 1024 * 1024 * 1024; - cout << "[extractor] Sorting used nodes ... " << flush; + std::cout << "[extractor] Sorting used nodes ... " << std::flush; stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Erasing duplicate nodes ... " << flush; - stxxl::vector::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ; + std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush; + stxxl::vector::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ; usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() ); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Sorting all nodes ... " << flush; + std::cout << "[extractor] Sorting all nodes ... " << std::flush; stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Sorting used ways ... " << flush; + std::cout << "[extractor] Sorting used ways ... " << std::flush; stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; - cout << "[extractor] Sorting restrctns. by from... " << flush; + std::cout << "[extractor] Sorting restrctns. by from... " << std::flush; stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; - cout << "[extractor] Fixing restriction starts ... " << flush; + std::cout << "[extractor] Fixing restriction starts ... " << std::flush; STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin(); STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin(); @@ -79,16 +79,16 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const ++restrictionsIT; } - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Sorting restrctns. by to ... " << flush; + std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush; stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); unsigned usableRestrictionsCounter(0); - cout << "[extractor] Fixing restriction ends ... " << flush; + std::cout << "[extractor] Fixing restriction ends ... " << std::flush; restrictionsIT = restrictionsVector.begin(); wayStartAndEndEdgeIT = wayStartEndVector.begin(); while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) { @@ -116,11 +116,11 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const } ++restrictionsIT; } - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; INFO("usable restrictions: " << usableRestrictionsCounter ); //serialize restrictions - ofstream restrictionsOutstream; - restrictionsOutstream.open(restrictionsFileName.c_str(), ios::binary); + std::ofstream restrictionsOutstream; + restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary); restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned)); for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) { if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) { @@ -129,11 +129,11 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const } restrictionsOutstream.close(); - ofstream fout; - fout.open(outputFileName.c_str(), ios::binary); + std::ofstream fout; + fout.open(outputFileName.c_str(), std::ios::binary); fout.write((char*)&usedNodeCounter, sizeof(unsigned)); time = get_timestamp(); - cout << "[extractor] Confirming/Writing used nodes ... " << flush; + std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush; STXXLNodeVector::iterator nodesIT = allNodes.begin(); STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin(); @@ -154,24 +154,24 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const } } - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; - cout << "[extractor] setting number of nodes ... " << flush; - ios::pos_type positionInFile = fout.tellp(); - fout.seekp(ios::beg); + std::cout << "[extractor] setting number of nodes ... " << std::flush; + std::ios::pos_type positionInFile = fout.tellp(); + fout.seekp(std::ios::beg); fout.write((char*)&usedNodeCounter, sizeof(unsigned)); fout.seekp(positionInFile); - cout << "ok" << endl; + std::cout << "ok" << std::endl; time = get_timestamp(); // Sort edges by start. - cout << "[extractor] Sorting edges by start ... " << flush; + std::cout << "[extractor] Sorting edges by start ... " << std::flush; stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Setting start coords ... " << flush; + std::cout << "[extractor] Setting start coords ... " << std::flush; fout.write((char*)&usedEdgeCounter, sizeof(unsigned)); // Traverse list of edges and nodes in parallel and set start coord nodesIT = allNodes.begin(); @@ -191,16 +191,16 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const ++edgeIT; } } - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); // Sort Edges by target - cout << "[extractor] Sorting edges by target ... " << flush; + std::cout << "[extractor] Sorting edges by target ... " << std::flush; stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time = get_timestamp(); - cout << "[extractor] Setting target coords ... " << flush; + std::cout << "[extractor] Setting target coords ... " << std::flush; // Traverse list of edges and nodes in parallel and set target coord nodesIT = allNodes.begin(); edgeIT = allEdges.begin(); @@ -245,8 +245,8 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&one, sizeof(short)); break; default: - cerr << "[error] edge with no direction: " << edgeIT->direction << endl; - assert(false); + std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl; + assert(false); break; } fout.write((char*)&intWeight, sizeof(int)); @@ -261,28 +261,28 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const ++edgeIT; } } - cout << "ok, after " << get_timestamp() - time << "s" << endl; - cout << "[extractor] setting number of edges ... " << flush; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; + std::cout << "[extractor] setting number of edges ... " << std::flush; fout.seekp(positionInFile); fout.write((char*)&usedEdgeCounter, sizeof(unsigned)); fout.close(); - cout << "ok" << endl; + std::cout << "ok" << std::endl; time = get_timestamp(); - cout << "[extractor] writing street name index ... " << flush; + std::cout << "[extractor] writing street name index ... " << std::flush; std::string nameOutFileName = (outputFileName + ".names"); - ofstream nameOutFile(nameOutFileName.c_str(), ios::binary); + std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary); unsigned sizeOfNameIndex = nameVector.size(); nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned)); - BOOST_FOREACH(string str, nameVector) { + BOOST_FOREACH(const std::string & str, nameVector) { unsigned lengthOfRawString = strlen(str.c_str()); nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned)); nameOutFile.write(str.c_str(), lengthOfRawString); } nameOutFile.close(); - cout << "ok, after " << get_timestamp() - time << "s" << endl; + std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; // time = get_timestamp(); // cout << "[extractor] writing address list ... " << flush; @@ -298,8 +298,8 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges"); - } catch ( const exception& e ) { - cerr << "Caught Execption:" << e.what() << endl; + } catch ( const std::exception& e ) { + std::cerr << "Caught Execption:" << e.what() << std::endl; } } diff --git a/typedefs.h b/typedefs.h index 852e71ad6..b65307859 100644 --- a/typedefs.h +++ b/typedefs.h @@ -21,13 +21,18 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef TYPEDEFS_H_ #define TYPEDEFS_H_ +#include +#include +#include + +// To fix long and long long woes +#include +#include + #ifdef __APPLE__ #include #endif -#include -#include -#include #include using namespace std; @@ -53,7 +58,7 @@ using namespace std; #define M_PI 3.14159265358979323846 #endif -//Necessary workaround for Windows as VS doesn't implement C99 +// Necessary workaround for Windows as VS doesn't implement C99 #ifdef _MSC_VER template digitT round(digitT x) { @@ -66,7 +71,7 @@ typedef unsigned int NodeID; typedef unsigned int EdgeID; typedef unsigned int EdgeWeight; -static const NodeID SPECIAL_NODEID = UINT_MAX; -static const EdgeID SPECIAL_EDGEID = UINT_MAX; +static const NodeID SPECIAL_NODEID = boost::integer_traits::const_max; +static const EdgeID SPECIAL_EDGEID = boost::integer_traits::const_max; #endif /* TYPEDEFS_H_ */ From 8fc8a4e303b7ceb48c1e4ec50ac0cf64cc957802 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 29 Dec 2012 21:02:26 +0100 Subject: [PATCH 005/161] Removing last remaining 'using namespace std' statement --- Algorithms/ObjectToBase64.h | 6 +++--- DataStructures/InputReaderFactory.h | 10 +++++----- DataStructures/SearchEngine.h | 6 +++--- Extractor/ExtractorCallbacks.cpp | 2 +- Extractor/ExtractorStructs.h | 10 +++++----- Extractor/XMLParser.h | 5 ++--- extractor.cpp | 4 ++-- typedefs.h | 7 ------- 8 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Algorithms/ObjectToBase64.h b/Algorithms/ObjectToBase64.h index fab161b21..8d69c0a8a 100644 --- a/Algorithms/ObjectToBase64.h +++ b/Algorithms/ObjectToBase64.h @@ -33,12 +33,12 @@ or see http://www.gnu.org/licenses/agpl.txt. typedef boost::archive::iterators::base64_from_binary< - boost::archive::iterators::transform_width + boost::archive::iterators::transform_width > base64_t; typedef boost::archive::iterators::transform_width< - boost::archive::iterators::binary_from_base64, 8, 6 + boost::archive::iterators::binary_from_base64, 8, 6 > binary_t; template @@ -54,7 +54,7 @@ static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) template static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) { try { - string encoded(_encoded); + std::string encoded(_encoded); //replace "-" with "+" and "_" with "/" replaceAll(encoded, "-", "+"); replaceAll(encoded, "_", "/"); diff --git a/DataStructures/InputReaderFactory.h b/DataStructures/InputReaderFactory.h index 552eb7370..f58232f79 100644 --- a/DataStructures/InputReaderFactory.h +++ b/DataStructures/InputReaderFactory.h @@ -43,21 +43,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) { return read; } else if(BZ_STREAM_END == context->error) { BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused); - if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadGetUnused" << endl; exit(-1);}; + if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <nUnused;i++) { context->unused[i] = unusedTmp[i]; } BZ2_bzReadClose(&context->error, context->bz2); - if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadClose" << endl; exit(-1);}; + if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <error = BZ_STREAM_END; // set to the stream end for next call to this function if(0 == context->nUnused && feof(context->file)) { return read; } else { context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused); - if(NULL == context->bz2){ cerr << "Could not open file" << endl; exit(-1);}; + if(NULL == context->bz2){std::cerr << "Could not open file" <error = false; diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h index d0cf25191..bd3e42005 100644 --- a/DataStructures/SearchEngine.h +++ b/DataStructures/SearchEngine.h @@ -48,10 +48,10 @@ template struct SearchEngineData { typedef SearchEngineHeapPtr HeapPtr; typedef GraphT Graph; - SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) :graph(g), nodeHelpDesk(nh), names(n) {} + SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) :graph(g), nodeHelpDesk(nh), names(n) {} const GraphT * graph; NodeInformationHelpDesk * nodeHelpDesk; - std::vector & names; + std::vector & names; static HeapPtr forwardHeap; static HeapPtr backwardHeap; static HeapPtr forwardHeap2; @@ -113,7 +113,7 @@ public: ShortestPathRouting shortestPath; AlternativeRouting alternativePaths; - SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) : + SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) : _queryData(g, nh, n), shortestPath(_queryData), alternativePaths(_queryData) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 5423d8970..3db1d8d8b 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -92,7 +92,7 @@ bool ExtractorCallbacks::wayFunction(_Way &w) { std::reverse( w.path.begin(), w.path.end() ); } - for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { + for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted)); externalMemory->usedNodeIDs.push_back(w.path[n]); } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index ebd40fc66..36194f119 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -110,7 +110,7 @@ struct _Edge { return _Edge(0,0); } static _Edge max_value() { - return _Edge((numeric_limits::max)(), (numeric_limits::max)()); + return _Edge((std::numeric_limits::max)(), (std::numeric_limits::max)()); } }; @@ -125,10 +125,10 @@ struct _WayIDStartAndEndEdge { _WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {} static _WayIDStartAndEndEdge min_value() { - return _WayIDStartAndEndEdge((numeric_limits::min)(), (numeric_limits::min)(), (numeric_limits::min)(), (numeric_limits::min)(), (numeric_limits::min)()); + return _WayIDStartAndEndEdge((std::numeric_limits::min)(), (std::numeric_limits::min)(), (std::numeric_limits::min)(), (std::numeric_limits::min)(), (std::numeric_limits::min)()); } static _WayIDStartAndEndEdge max_value() { - return _WayIDStartAndEndEdge((numeric_limits::max)(), (numeric_limits::max)(), (numeric_limits::max)(), (numeric_limits::max)(), (numeric_limits::max)()); + return _WayIDStartAndEndEdge((std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)()); } }; @@ -202,7 +202,7 @@ struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool> } }; -inline string GetRandomString() { +inline std::string GetRandomString() { char s[128]; static const char alphanum[] = "0123456789" @@ -213,7 +213,7 @@ inline string GetRandomString() { s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; } s[127] = 0; - return string(s); + return std::string(s); } #endif /* EXTRACTORSTRUCTS_H_ */ diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index c9d665dc3..820dcb596 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -75,7 +75,7 @@ public: if(!externalMemory->nodeFunction(n)) std::cerr << "[XMLParser] dense node not parsed" << std::endl; } catch (const luabind::error &er) { - cerr << er.what() << endl; + std::cerr << er.what() << std::endl; lua_State* Ler=er.state(); report_errors(Ler, -1); } catch (std::exception & e) { @@ -86,7 +86,6 @@ public: } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - string name; _Way way = _ReadXMLWay( ); /** Pass the unpacked way to the LUA call back **/ @@ -101,7 +100,7 @@ public: std::cerr << "[PBFParser] way not parsed" << std::endl; } } catch (const luabind::error &er) { - cerr << er.what() << endl; + std::cerr << er.what() << std::endl; lua_State* Ler=er.state(); report_errors(Ler, -1); } catch (std::exception & e) { diff --git a/extractor.cpp b/extractor.cpp index c7b6decb2..5d4e66fbc 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -67,12 +67,12 @@ int main (int argc, char *argv[]) { isPBF = true; } } - if(pos!=string::npos) { + if(pos!=std::string::npos) { outputFileName.replace(pos, 8, ".osrm"); restrictionsFileName.replace(pos, 8, ".osrm.restrictions"); } else { pos=outputFileName.find(".osm"); - if(pos!=string::npos) { + if(pos!=std::string::npos) { outputFileName.replace(pos, 5, ".osrm"); restrictionsFileName.replace(pos, 5, ".osrm.restrictions"); } else { diff --git a/typedefs.h b/typedefs.h index b65307859..32807130e 100644 --- a/typedefs.h +++ b/typedefs.h @@ -35,13 +35,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include -using namespace std; - -#ifdef STXXL_VERBOSE_LEVEL -#undef STXXL_VERBOSE_LEVEL -#endif -#define STXXL_VERBOSE_LEVEL -100 - #define INFO(x) do {std::cout << "[info " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); #define ERR(x) do {std::cerr << "[error " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0); #define WARN(x) do {std::cerr << "[warn " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); From 0235cf5d8e9e1d3d8b15513ffaf1bbe8da3fcad0 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 31 Dec 2012 11:20:44 +0100 Subject: [PATCH 006/161] remove unused struct MinimalEdgeData --- DataStructures/ImportEdge.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index a90cd474d..27fc3cfe8 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -123,13 +123,6 @@ public: bool _backward:1; }; -struct MinimalEdgeData { -public: - EdgeWeight distance; - bool forward; - bool backward; -}; - typedef NodeBasedEdge ImportEdge; #endif // EDGE_H From f4431ed83727966ed269221ff6e3f9cc9f7f0e4e Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 1 Jan 2013 17:10:30 +0100 Subject: [PATCH 007/161] simple rake tasks for extracting/preparing separately --- Rakefile | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 727412797..3f4ecbcba 100644 --- a/Rakefile +++ b/Rakefile @@ -16,7 +16,7 @@ areas = { :kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' }, :frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' }, :regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' }, - :dk => { :country => 'denmark', :bbox => nil }, + :denmark => { :country => 'denmark', :bbox => nil }, :skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' } } @@ -123,6 +123,20 @@ task :process => :setup do end end +desc "Extract OSM data." +task :extract => :setup do + Dir.chdir DATA_FOLDER do + raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua" + end +end + +desc "Prepare OSM data." +task :prepare => :setup do + Dir.chdir DATA_FOLDER do + raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua" + end +end + desc "Delete preprocessing files." task :clean do File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm") From 0f4207f85e1dca768429af8217dd9b10d0b34666 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 1 Jan 2013 17:25:40 +0100 Subject: [PATCH 008/161] show total running time when extracting --- extractor.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extractor.cpp b/extractor.cpp index 5d4e66fbc..35b5c5714 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -39,6 +39,8 @@ typedef BaseConfiguration ExtractorConfiguration; ExtractorCallbacks * extractCallBacks; int main (int argc, char *argv[]) { + double earliestTime = get_timestamp(); + if(argc < 2) { ERR("usage: \n" << argv[0] << " []"); } @@ -113,7 +115,8 @@ int main (int argc, char *argv[]) { stringMap.clear(); delete parser; delete extractCallBacks; - INFO("finished"); + INFO("finished after " << get_timestamp() - earliestTime << "s"); + std::cout << "\nRun:\n" "./osrm-prepare " << outputFileName << " " << restrictionsFileName << std::endl; return 0; From ff417fac012e2ce22875e8ad2b1965f3072325a4 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 1 Jan 2013 18:41:38 +0100 Subject: [PATCH 009/161] update ferry tests --- features/bicycle/ferry.feature | 75 +------------- features/testbot/ferry.feature | 178 +++++++++++++++++++++++++++------ 2 files changed, 147 insertions(+), 106 deletions(-) diff --git a/features/bicycle/ferry.feature b/features/bicycle/ferry.feature index 762774cf1..87d9773c9 100644 --- a/features/bicycle/ferry.feature +++ b/features/bicycle/ferry.feature @@ -60,77 +60,4 @@ Feature: Bike - Handle ferry routes When I route I should get | from | to | route | time | | a | d | abcd | 3600s +-1 | - | d | a | abcd | 3600s +-1 | - - Scenario: Bike - Ferry duration, connected routes - Given the node map - | x | | | | | | | | y | - | | a | b | c | d | e | f | g | | - - And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yg | primary | | | | - | abcd | | ferry | yes | 0:30 | - | defg | | ferry | yes | 0:30 | - - When I route I should get - | from | to | route | time | - | a | g | abcd,defg | 3600s +-1 | - | g | a | defg,abcd | 3600s +-1 | - - Scenario: Bike - Prefer road when faster than ferry - Given the node map - | x | a | b | c | | - | | | | | d | - | y | g | f | e | | - - And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yg | primary | | | | - | xy | primary | | | | - | abcd | | ferry | yes | 0:01 | - | defg | | ferry | yes | 0:01 | - - When I route I should get - | from | to | route | time | - | a | g | xa,xy,yg | 60s +-25% | - | g | a | yg,xy,xa | 60s +-25% | - - Scenario: Bike - Long winding ferry route - Given the node map - | x | | b | | d | | f | | y | - | | a | | c | | e | | g | | - - And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yg | primary | | | | - | abcdefg | | ferry | yes | 6:30 | - - When I route I should get - | from | to | route | time | - | a | g | abcdefg | 23400s +-1 | - | g | a | abcdefg | 23400s +-1 | - - @todo - Scenario: Bike - Ferry duration, individual parts - Given the node map - | x | y | | z | | | v | - | a | b | | c | | | d | - - And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yb | primary | | | | - | zc | primary | | | | - | vd | primary | | | | - | abcd | | ferry | yes | 1:00 | - - When I route I should get - | from | to | route | time | - | a | d | abcd | 3600s +-1 | - | a | b | abcd | 600s +-1 | - | b | c | abcd | 1200s +-1 | - | c | d | abcd | 1800s +-1 | + | d | a | abcd | 3600s +-1 | \ No newline at end of file diff --git a/features/testbot/ferry.feature b/features/testbot/ferry.feature index aadd083c0..7bd43534e 100644 --- a/features/testbot/ferry.feature +++ b/features/testbot/ferry.feature @@ -7,21 +7,61 @@ Feature: Testbot - Handle ferry routes Scenario: Testbot - Ferry duration, single node Given the node map | a | b | c | d | - | | | e | f | - | | | g | h | - | | | i | j | - + | e | f | g | h | + | i | j | k | l | + | m | n | o | p | + | q | r | s | t | + And the ways - | nodes | highway | route | bicycle | duration | - | ab | primary | | | | - | cd | primary | | | | - | ef | primary | | | | - | gh | primary | | | | - | ij | primary | | | | - | bc | | ferry | yes | 0:01 | - | be | | ferry | yes | 0:10 | - | bg | | ferry | yes | 1:00 | - | bi | | ferry | yes | 10:00 | + | nodes | highway | route | duration | + | ab | primary | | | + | cd | primary | | | + | ef | primary | | | + | gh | primary | | | + | ij | primary | | | + | kl | primary | | | + | mn | primary | | | + | op | primary | | | + | qr | primary | | | + | st | primary | | | + | bc | | ferry | 0:01 | + | fg | | ferry | 0:10 | + | jk | | ferry | 1:00 | + | no | | ferry | 24:00 | + | rs | | ferry | 96:00 | + + When I route I should get + | from | to | route | time | + | b | c | bc | 60s +-1 | + | f | g | fg | 600s +-1 | + | j | k | jk | 3600s +-1 | + | n | o | no | 86400s +-1 | + | r | s | rs | 345600s +-1 | + + @todo + Scenario: Testbot - Week long ferry routes + Given the node map + | a | b | c | d | + | e | f | g | h | + | i | j | k | l | + + And the ways + | nodes | highway | route | duration | + | ab | primary | | | + | cd | primary | | | + | ef | primary | | | + | gh | primary | | | + | ij | primary | | | + | kl | primary | | | + | bc | | ferry | 24:00 | + | fg | | ferry | 168:00 | + | jk | | ferry | 720:00 | + + When I route I should get + | from | to | route | time | + | b | c | bc | 86400s +-1 | + | f | g | fg | 604800s +-1 | + | j | k | jk | 259200s +-1 | Scenario: Testbot - Ferry duration, multiple nodes Given the node map @@ -29,33 +69,107 @@ Feature: Testbot - Handle ferry routes | | a | b | c | d | | And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yd | primary | | | | - | abcd | | ferry | yes | 1:00 | + | nodes | highway | route | duration | + | xa | primary | | | + | yd | primary | | | + | ad | | ferry | 1:00 | When I route I should get | from | to | route | time | - | a | d | abcd | 3600s +-1 | - | d | a | abcd | 3600s +-1 | + | a | d | ad | 3600s +-1 | + | d | a | ad | 3600s +-1 | @todo - Scenario: Bike - Ferry duration, individual parts + Scenario: Testbot - Ferry duration, individual parts, fast + Given a grid size of 10000 meters Given the node map | x | y | | z | | | v | | a | b | | c | | | d | And the ways - | nodes | highway | route | bicycle | duration | - | xa | primary | | | | - | yb | primary | | | | - | zc | primary | | | | - | vd | primary | | | | - | abcd | | ferry | yes | 1:00 | + | nodes | highway | route | duration | + | xa | primary | | | + | yb | primary | | | + | zc | primary | | | + | vd | primary | | | + | abcd | | ferry | 0:06 | When I route I should get - | from | to | route | time | - | a | d | abcd | 3600s +-1 | - | a | b | abcd | 600s +-1 | - | b | c | abcd | 1200s +-1 | - | c | d | abcd | 1800s +-1 | \ No newline at end of file + | from | to | route | time | + | a | d | abcd | 360s +-1 | + | a | b | abcd | 60s +-1 | + | b | c | abcd | 120s +-1 | + | c | d | abcd | 180s +-1 | + + @todo + Scenario: Testbot - Ferry duration, individual parts, slow + Given the node map + | x | y | | z | | | v | + | a | b | | c | | | d | + + And the ways + | nodes | highway | route | duration | + | xa | primary | | | + | yb | primary | | | + | zc | primary | | | + | vd | primary | | | + | abcd | | ferry | 1:00 | + + When I route I should get + | from | to | route | time | + | a | d | abcd | 3600s ~1% | + | a | b | abcd | 600s ~1% | + | b | c | abcd | 1200s ~1% | + | c | d | abcd | 1800s ~1% | + + Scenario: Testbot - Ferry duration, connected routes + Given the node map + | x | | | | d | | | | y | + | | a | b | c | | e | f | g | t | + + And the ways + | nodes | highway | route | duration | + | xa | primary | | | + | yg | primary | | | + | abcd | | ferry | 0:30 | + | defg | | ferry | 0:30 | + + When I route I should get + | from | to | route | time | + | a | g | abcd,defg | 3600s +-1 | + | g | a | defg,abcd | 3600s +-1 | + + Scenario: Testbot - Prefer road when faster than ferry + Given the node map + | x | a | b | c | | + | | | | | d | + | y | g | f | e | | + + And the ways + | nodes | highway | route | duration | + | xa | primary | | | + | yg | primary | | | + | xy | primary | | | + | abcd | | ferry | 0:01 | + | defg | | ferry | 0:01 | + + When I route I should get + | from | to | route | time | + | a | g | xa,xy,yg | 60s +-25% | + | g | a | yg,xy,xa | 60s +-25% | + + Scenario: Testbot - Long winding ferry route + Given the node map + | x | | b | | d | | f | | y | + | | a | | c | | e | | g | | + + And the ways + | nodes | highway | route | duration | + | xa | primary | | | + | yg | primary | | | + | abcdefg | | ferry | 6:30 | + + When I route I should get + | from | to | route | time | + | a | g | abcdefg | 23400s +-1 | + | g | a | abcdefg | 23400s +-1 | From c4ed218a7abd1f9be59ee93ae338a554f4bccf51 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 1 Jan 2013 23:01:52 +0100 Subject: [PATCH 010/161] Revert "remove unused struct MinimalEdgeData" This reverts commit 0235cf5d8e9e1d3d8b15513ffaf1bbe8da3fcad0. --- DataStructures/ImportEdge.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index 27fc3cfe8..a90cd474d 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -123,6 +123,13 @@ public: bool _backward:1; }; +struct MinimalEdgeData { +public: + EdgeWeight distance; + bool forward; + bool backward; +}; + typedef NodeBasedEdge ImportEdge; #endif // EDGE_H From 4aa7ade32cf3c8758f86524ed44f2e37e123e148 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 1 Jan 2013 23:20:16 +0100 Subject: [PATCH 011/161] ordering includes alphabetically --- Extractor/ScriptingEnvironment.cpp | 2 +- createHierarchy.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index dbeb2f5f0..2ef215cd1 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -26,8 +26,8 @@ extern "C" { #include "ScriptingEnvironment.h" #include "../typedefs.h" -#include "../Util/OpenMPWrapper.h" #include "../Util/LuaUtil.h" +#include "../Util/OpenMPWrapper.h" ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { diff --git a/createHierarchy.cpp b/createHierarchy.cpp index eb06a8842..2596d312b 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -44,10 +44,10 @@ extern "C" { #include "DataStructures/NNGrid.h" #include "DataStructures/QueryEdge.h" #include "Util/BaseConfiguration.h" -#include "Util/InputFileUtil.h" #include "Util/GraphLoader.h" -#include "Util/StringUtil.h" +#include "Util/InputFileUtil.h" #include "Util/LuaUtil.h" +#include "Util/StringUtil.h" using namespace std; From c5e8bed1fbbe7bc5599917d4e3ffda8a941d1d8f Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Wed, 2 Jan 2013 00:02:48 +0100 Subject: [PATCH 012/161] increase stxxl allocation used in tests, to avoid reallocation --- test/.stxxl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/.stxxl b/test/.stxxl index d26050d7f..b1765e2c0 100644 --- a/test/.stxxl +++ b/test/.stxxl @@ -1 +1 @@ -disk=/tmp/stxxl,1,syscall +disk=/tmp/stxxl,10,syscall From 9379d2462ebac209759a407d2f99c213b9d6ce8c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 2 Jan 2013 00:32:34 +0100 Subject: [PATCH 013/161] Splitting monolithic extraction code into compile units --- Extractor/BaseParser.h | 4 +- Extractor/PBFParser.h | 599 ++++------------------------------------- Extractor/XMLParser.h | 311 ++------------------- 3 files changed, 85 insertions(+), 829 deletions(-) diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index f46b19fea..adf417a73 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -27,10 +27,12 @@ extern "C" { #include } +#include + #include "ScriptingEnvironment.h" template -class BaseParser { +class BaseParser : boost::noncopyable { public: virtual ~BaseParser() {} virtual bool Init() = 0; diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index 24f80c924..be6920d8c 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -1,586 +1,99 @@ /* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU AFFERO General Public License as published by + the Free Software Foundation; either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + or see http://www.gnu.org/licenses/agpl.txt. */ #ifndef PBFPARSER_H_ #define PBFPARSER_H_ -#include +#include #include #include -#include #include #include +#include + #include "../typedefs.h" +#include "../DataStructures/HashTable.h" +#include "../DataStructures/ConcurrentQueue.h" +#include "../Util/MachineInfo.h" +#include "../Util/OpenMPWrapper.h" #include "BaseParser.h" #include "ExtractorCallbacks.h" #include "ExtractorStructs.h" #include "ScriptingEnvironment.h" -#include "../DataStructures/HashTable.h" -#include "../DataStructures/ConcurrentQueue.h" -#include "../Util/OpenMPWrapper.h" class PBFParser : public BaseParser { - -// typedef BaseParser super; - + enum EntityType { TypeNode = 1, TypeWay = 2, TypeRelation = 4, TypeDenseNode = 8 } ; - - enum Endianness { - LittleEndian = 1, - BigEndian = 2 - }; - + struct _ThreadData { int currentGroupID; int currentEntityID; short entityTypeIndicator; - + OSMPBF::BlobHeader PBFBlobHeader; OSMPBF::Blob PBFBlob; - + OSMPBF::HeaderBlock PBFHeaderBlock; OSMPBF::PrimitiveBlock PBFprimitiveBlock; - + std::vector charBuffer; }; - + public: - PBFParser(const char * fileName) : externalMemory(NULL){ - GOOGLE_PROTOBUF_VERIFY_VERSION; - //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? - //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. - threadDataQueue = boost::make_shared >( 2500 ); /* Max 2500 items in queue, hardcoded. */ - input.open(fileName, std::ios::in | std::ios::binary); - - if (!input) { - std::cerr << fileName << ": File not found." << std::endl; - } - -#ifndef NDEBUG - blockCount = 0; - groupCount = 0; -#endif - } - - void RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; - } - - //call by value, but who cares. It is done once. - void RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - scriptingEnvironment = _se; - } - - ~PBFParser() { - if(input.is_open()) - input.close(); - - // Clean up any leftover ThreadData objects in the queue - _ThreadData* td; - while (threadDataQueue->try_pop(td)) { - delete td; - } - google::protobuf::ShutdownProtobufLibrary(); - -#ifndef NDEBUG - DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups"); -#endif - } - - inline bool Init() { - _ThreadData initData; - /** read Header */ - if(!readPBFBlobHeader(input, &initData)) { - return false; - } - - if(readBlob(input, &initData)) { - if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) { - std::cerr << "[error] Header not parseable!" << std::endl; - return false; - } - - for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { - const std::string& feature = initData.PBFHeaderBlock.required_features( i ); - bool supported = false; - if ( "OsmSchema-V0.6" == feature ) - supported = true; - else if ( "DenseNodes" == feature ) - supported = true; - - if ( !supported ) { - std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; - return false; - } - } - } else { - std::cerr << "[error] blob not loaded!" << std::endl; - } - return true; - } - - inline void ReadData() { - bool keepRunning = true; - do { - _ThreadData *threadData = new _ThreadData(); - keepRunning = readNextBlock(input, threadData); - - if (keepRunning) - threadDataQueue->push(threadData); - else { - threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered - delete threadData; - } - } while(keepRunning); - } - - inline void ParseData() { - while (1) { - _ThreadData *threadData; - threadDataQueue->wait_and_pop(threadData); - if (threadData == NULL) { - INFO("Parse Data Thread Finished"); - threadDataQueue->push(NULL); // Signal end of data for other threads - break; - } - - loadBlock(threadData); - - for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) { - threadData->currentGroupID = i; - loadGroup(threadData); - - if(threadData->entityTypeIndicator == TypeNode) - parseNode(threadData); - if(threadData->entityTypeIndicator == TypeWay) - parseWay(threadData); - if(threadData->entityTypeIndicator == TypeRelation) - parseRelation(threadData); - if(threadData->entityTypeIndicator == TypeDenseNode) - parseDenseNode(threadData); - } - - delete threadData; - threadData = NULL; - } - } - - inline bool Parse() { - // Start the read and parse threads - boost::thread readThread(boost::bind(&PBFParser::ReadData, this)); - - //Open several parse threads that are synchronized before call to - boost::thread parseThread(boost::bind(&PBFParser::ParseData, this)); - - // Wait for the threads to finish - readThread.join(); - parseThread.join(); - - return true; - } - + PBFParser(const char * fileName); + virtual ~PBFParser(); + + void RegisterCallbacks(ExtractorCallbacks * em); + void RegisterScriptingEnvironment(ScriptingEnvironment & _se); + + inline bool Init(); + inline bool Parse(); + private: - - inline void parseDenseNode(_ThreadData * threadData) { - const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense(); - int denseTagIndex = 0; - int m_lastDenseID = 0; - int m_lastDenseLatitude = 0; - int m_lastDenseLongitude = 0; - - ImportNode n; - std::vector nodesToParse; - for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { - n.Clear(); - m_lastDenseID += dense.id( i ); - m_lastDenseLatitude += dense.lat( i ); - m_lastDenseLongitude += dense.lon( i ); - n.id = m_lastDenseID; - n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; - n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; - while (denseTagIndex < dense.keys_vals_size()) { - const int tagValue = dense.keys_vals( denseTagIndex ); - if(tagValue == 0) { - ++denseTagIndex; - break; - } - const int keyValue = dense.keys_vals ( denseTagIndex+1 ); - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data(); - const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data(); - n.keyVals.Add(key, value); - denseTagIndex += 2; - } - nodesToParse.push_back(n); - } - - unsigned endi_nodes = nodesToParse.size(); -#pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_nodes; ++i) { - ImportNode &n = nodesToParse[i]; - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "node_function", - boost::ref(n) - ); - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } -// catch (...) { -// ERR("Unknown error occurred during PBF dense node parsing!"); -// } - } - - - BOOST_FOREACH(ImportNode &n, nodesToParse) { - if(!externalMemory->nodeFunction(n)) - std::cerr << "[PBFParser] dense node not parsed" << std::endl; - } - } - - inline void parseNode(_ThreadData * ) { - ERR("Parsing of simple nodes not supported. PBF should use dense nodes"); - } - - inline void parseRelation(_ThreadData * threadData) { - //TODO: leave early, if relatio is not a restriction - //TODO: reuse rawRestriction container - const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); - for(int i = 0; i < group.relations_size(); ++i ) { - const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); - bool isRestriction = false; - bool isOnlyRestriction = false; - for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) { - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); - const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); - if ("type" == key) { - if( "restriction" == val) - isRestriction = true; - else - break; - } - if ("restriction" == key) { - if(val.find("only_") == 0) - isOnlyRestriction = true; - } - - } - if(isRestriction) { - long long lastRef = 0; - _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); - for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { - std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); - lastRef += inputRelation.memids(rolesIndex); - - if(false == ("from" == role || "to" == role || "via" == role)) { - continue; - } - - switch(inputRelation.types(rolesIndex)) { - case 0: //node - if("from" == role || "to" == role) //Only via should be a node - continue; - assert("via" == role); - if(UINT_MAX != currentRestrictionContainer.viaNode) - currentRestrictionContainer.viaNode = UINT_MAX; - assert(UINT_MAX == currentRestrictionContainer.viaNode); - currentRestrictionContainer.restriction.viaNode = lastRef; - break; - case 1: //way - assert("from" == role || "to" == role || "via" == role); - if("from" == role) { - currentRestrictionContainer.fromWay = lastRef; - } - if ("to" == role) { - currentRestrictionContainer.toWay = lastRef; - } - if ("via" == role) { - assert(currentRestrictionContainer.restriction.toNode == UINT_MAX); - currentRestrictionContainer.viaNode = lastRef; - } - break; - case 2: //relation, not used. relations relating to relations are evil. - continue; - assert(false); - break; - - default: //should not happen - //cout << "unknown"; - assert(false); - break; - } - } - // if(UINT_MAX != currentRestriction.viaNode) { - // cout << "restr from " << currentRestriction.from << " via "; - // cout << "node " << currentRestriction.viaNode; - // cout << " to " << currentRestriction.to << endl; - // } - if(!externalMemory->restrictionFunction(currentRestrictionContainer)) - std::cerr << "[PBFParser] relation not parsed" << std::endl; - } - } - } - - inline void parseWay(_ThreadData * threadData) { - _Way w; - std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); - for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { - w.Clear(); - const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); - w.id = inputWay.id(); - unsigned pathNode(0); - for(int i = 0; i < inputWay.refs_size(); ++i) { - pathNode += inputWay.refs(i); - w.path.push_back(pathNode); - } - assert(inputWay.keys_size() == inputWay.vals_size()); - for(int i = 0; i < inputWay.keys_size(); ++i) { - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); - const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); - w.keyVals.Add(key, val); - } - - waysToParse.push_back(w); - } - - unsigned endi_ways = waysToParse.size(); -#pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_ways; ++i) { - _Way & w = waysToParse[i]; - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "way_function", - boost::ref(w), - w.path.size() - ); - - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } -// catch (...) { -// ERR("Unknown error!"); -// } - } - - BOOST_FOREACH(_Way & w, waysToParse) { - if(!externalMemory->wayFunction(w)) { - std::cerr << "[PBFParser] way not parsed" << std::endl; - } - } - } - - inline void loadGroup(_ThreadData * threadData) { -#ifndef NDEBUG - ++groupCount; -#endif - - const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); - threadData->entityTypeIndicator = 0; - if ( group.nodes_size() != 0 ) { - threadData->entityTypeIndicator = TypeNode; - } - if ( group.ways_size() != 0 ) { - threadData->entityTypeIndicator = TypeWay; - } - if ( group.relations_size() != 0 ) { - threadData->entityTypeIndicator = TypeRelation; - } - if ( group.has_dense() ) { - threadData->entityTypeIndicator = TypeDenseNode; - assert( group.dense().id_size() != 0 ); - } - assert( threadData->entityTypeIndicator != 0 ); - } - - inline void loadBlock(_ThreadData * threadData) { -#ifndef NDEBUG - ++blockCount; -#endif - threadData->currentGroupID = 0; - threadData->currentEntityID = 0; - } - - /* Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination */ - inline unsigned swapEndian(unsigned x) const { - if(getMachineEndianness() == LittleEndian) - return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) ); - return x; - } - - inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) { - int size(0); - stream.read((char *)&size, sizeof(int)); - size = swapEndian(size); - if(stream.eof()) { - return false; - } - if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) { - return false; - } - char *data = new char[size]; - stream.read(data, size*sizeof(data[0])); - - bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size); - delete[] data; - return dataSuccessfullyParsed; - } - - inline bool unpackZLIB(std::fstream &, _ThreadData * threadData) { - unsigned rawSize = threadData->PBFBlob.raw_size(); - char* unpackedDataArray = new char[rawSize]; - z_stream compressedDataStream; - compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data(); - compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size(); - compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray; - compressedDataStream.avail_out = rawSize; - compressedDataStream.zalloc = Z_NULL; - compressedDataStream.zfree = Z_NULL; - compressedDataStream.opaque = Z_NULL; - int ret = inflateInit( &compressedDataStream ); - if ( ret != Z_OK ) { - std::cerr << "[error] failed to init zlib stream" << std::endl; - delete[] unpackedDataArray; - return false; - } - - ret = inflate( &compressedDataStream, Z_FINISH ); - if ( ret != Z_STREAM_END ) { - std::cerr << "[error] failed to inflate zlib stream" << std::endl; - std::cerr << "[error] Error type: " << ret << std::endl; - delete[] unpackedDataArray; - return false; - } - - ret = inflateEnd( &compressedDataStream ); - if ( ret != Z_OK ) { - std::cerr << "[error] failed to deinit zlib stream" << std::endl; - delete[] unpackedDataArray; - return false; - } - - threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize); - std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin()); - delete[] unpackedDataArray; - return true; - } - - inline bool unpackLZMA(std::fstream &, _ThreadData * ) const { - return false; - } - - inline bool readBlob(std::fstream& stream, _ThreadData * threadData) { - if(stream.eof()) - return false; - - const int size = threadData->PBFBlobHeader.datasize(); - if ( size < 0 || size > MAX_BLOB_SIZE ) { - std::cerr << "[error] invalid Blob size:" << size << std::endl; - return false; - } - - char* data = new char[size]; - stream.read(data, sizeof(data[0])*size); - - if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) { - std::cerr << "[error] failed to parse blob" << std::endl; - delete[] data; - return false; - } - - if ( threadData->PBFBlob.has_raw() ) { - const std::string& data = threadData->PBFBlob.raw(); - threadData->charBuffer.clear(); - threadData->charBuffer.resize( data.size() ); - std::copy(data.begin(), data.end(), threadData->charBuffer.begin()); - } else if ( threadData->PBFBlob.has_zlib_data() ) { - if ( !unpackZLIB(stream, threadData) ) { - std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl; - delete[] data; - return false; - } - } else if ( threadData->PBFBlob.has_lzma_data() ) { - if ( !unpackLZMA(stream, threadData) ) - std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; - delete[] data; - return false; - } else { - std::cerr << "[error] Blob contains no data" << std::endl; - delete[] data; - return false; - } - delete[] data; - return true; - } - - inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData) { - if(stream.eof()) { - return false; - } - - if ( !readPBFBlobHeader(stream, threadData) ){ - return false; - } - - if ( threadData->PBFBlobHeader.type() != "OSMData" ) { - return false; - } - - if ( !readBlob(stream, threadData) ) { - return false; - } - - if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) { - ERR("failed to parse PrimitiveBlock"); - return false; - } - return true; - } - - //Is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3 - inline Endianness getMachineEndianness() const { - int i(1); - char *p = (char *) &i; - if (1 == p[0]) - return LittleEndian; - return BigEndian; - } - + inline void ReadData(); + inline void ParseData(); + inline void parseDenseNode(_ThreadData * threadData); + inline void parseNode(_ThreadData * ); + inline void parseRelation(_ThreadData * threadData); + inline void parseWay(_ThreadData * threadData); + + inline void loadGroup(_ThreadData * threadData); + inline void loadBlock(_ThreadData * threadData); + inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData); + inline bool unpackZLIB(std::fstream &, _ThreadData * threadData); + inline bool unpackLZMA(std::fstream &, _ThreadData * ); + inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ; + inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData); + static const int NANO = 1000 * 1000 * 1000; static const int MAX_BLOB_HEADER_SIZE = 64 * 1024; static const int MAX_BLOB_SIZE = 32 * 1024 * 1024; - + #ifndef NDEBUG /* counting the number of read blocks and groups */ unsigned groupCount; @@ -590,10 +103,8 @@ private: ExtractorCallbacks * externalMemory; /* the input stream to parse */ std::fstream input; - /* ThreadData Queue */ boost::shared_ptr > threadDataQueue; - ScriptingEnvironment scriptingEnvironment; }; diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index 820dcb596..f80ad48bc 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -1,306 +1,49 @@ /* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU AFFERO General Public License as published by + the Free Software Foundation; either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + or see http://www.gnu.org/licenses/agpl.txt. */ #ifndef XMLPARSER_H_ #define XMLPARSER_H_ -#include #include #include "../typedefs.h" #include "BaseParser.h" -#include "ExtractorStructs.h" #include "ExtractorCallbacks.h" #include "ScriptingEnvironment.h" -#include "../DataStructures/HashTable.h" -#include "../DataStructures/InputReaderFactory.h" class XMLParser : public BaseParser { public: - XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){ - WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); - inputReader = inputReaderFactory(filename); - } - virtual ~XMLParser() {} - - void RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; - } - - void RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - myLuaState = _se.getLuaStateForThreadID(0); - } - - bool Init() { - return (xmlTextReaderRead( inputReader ) == 1); - } - bool Parse() { - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int type = xmlTextReaderNodeType( inputReader ); - - //1 is Element - if ( type != 1 ) - continue; - - xmlChar* currentName = xmlTextReaderName( inputReader ); - if ( currentName == NULL ) - continue; - - if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { - ImportNode n = _ReadXMLNode( ); - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "node_function", - boost::ref(n) - ); - if(!externalMemory->nodeFunction(n)) - std::cerr << "[XMLParser] dense node not parsed" << std::endl; - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML node parsing!"); - } - } - - if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - _Way way = _ReadXMLWay( ); - - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "way_function", - boost::ref(way), - way.path.size() - ); - if(!externalMemory->wayFunction(way)) { - std::cerr << "[PBFParser] way not parsed" << std::endl; - } - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML way parsing!"); - } - } - if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { - _RawRestrictionContainer r = _ReadXMLRestriction(); - if(r.fromWay != UINT_MAX) { - if(!externalMemory->restrictionFunction(r)) { - std::cerr << "[XMLParser] restriction not parsed" << std::endl; - } - } - } - xmlFree( currentName ); - } - return true; - } - + XMLParser(const char * filename); + virtual ~XMLParser(); + void RegisterCallbacks(ExtractorCallbacks * em); + void RegisterScriptingEnvironment(ScriptingEnvironment & _se); + bool Init(); + bool Parse(); + private: - _RawRestrictionContainer _ReadXMLRestriction ( ) { - _RawRestrictionContainer restriction; - - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - if ( k != NULL && value != NULL ) { - if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ - if(0 == std::string((const char *) value).find("only_")) - restriction.restriction.flags.isOnly = true; - } - - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { - xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); - if ( ref != NULL ) { - xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); - xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); - if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { - restriction.toWay = atoi((const char*) ref); - } - if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { - restriction.fromWay = atoi((const char*) ref); - } - if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { - restriction.restriction.viaNode = atoi((const char*) ref); - } - - if(NULL != type) - xmlFree( type ); - if(NULL != role) - xmlFree( role ); - if(NULL != ref) - xmlFree( ref ); - } - } - xmlFree( childName ); - } - } - return restriction; - } - - _Way _ReadXMLWay( ) { - _Way way; - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader ); - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { - xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); - way.id = atoi((char*)id); - xmlFree(id); - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - // cout << "->k=" << k << ", v=" << value << endl; - if ( k != NULL && value != NULL ) { - - way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { - xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); - if ( ref != NULL ) { - way.path.push_back( atoi(( const char* ) ref ) ); - xmlFree( ref ); - } - } - xmlFree( childName ); - } - } - return way; - } - - ImportNode _ReadXMLNode( ) { - ImportNode node; - - xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); - if ( attribute != NULL ) { - node.lat = static_cast(100000.*atof(( const char* ) attribute ) ); - xmlFree( attribute ); - } - attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); - if ( attribute != NULL ) { - node.lon = static_cast(100000.*atof(( const char* ) attribute )); - xmlFree( attribute ); - } - attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); - if ( attribute != NULL ) { - node.id = atoi(( const char* ) attribute ); - xmlFree( attribute ); - } - - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader ); - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - // 1 = Element, 15 = EndElement - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - if ( k != NULL && value != NULL ) { - node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } - - xmlFree( childName ); - } - } - return node; - } + _RawRestrictionContainer _ReadXMLRestriction(); + _Way _ReadXMLWay(); + ImportNode _ReadXMLNode( ); /* Input Reader */ xmlTextReaderPtr inputReader; - - //holds the callback functions and storage for our temporary data ExtractorCallbacks * externalMemory; - lua_State *myLuaState; }; From 12a35c12148d58f21f9c8d2d029f8591d8ee1fd3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 2 Jan 2013 00:33:14 +0100 Subject: [PATCH 014/161] Splitting monolithic extraction code into compile units --- Util/MachineInfo.h | 28 +++++++++++++++++++++++++--- extractor.cpp | 1 + 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Util/MachineInfo.h b/Util/MachineInfo.h index 2849071a0..7c0f31c3b 100644 --- a/Util/MachineInfo.h +++ b/Util/MachineInfo.h @@ -30,8 +30,29 @@ extern "C" { #include #endif -/* Returns the physical memory size in kilobytes */ -unsigned GetPhysicalmemory(void){ +enum Endianness { + LittleEndian = 1, + BigEndian = 2 +}; + +//Function is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3 +inline Endianness getMachineEndianness() { + int i(1); + char *p = (char *) &i; + if (1 == p[0]) + return LittleEndian; + return BigEndian; +} + +// Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination +inline unsigned swapEndian(unsigned x) { + if(getMachineEndianness() == LittleEndian) + return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) ); + return x; +} + +// Returns the physical memory size in kilobytes +inline unsigned GetPhysicalmemory(void){ #if defined(SUN5) || defined(__linux__) return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)); @@ -61,4 +82,5 @@ unsigned GetPhysicalmemory(void){ #endif } -#endif +#endif // MACHINE_INFO_H + diff --git a/extractor.cpp b/extractor.cpp index 35b5c5714..d212a837e 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -32,6 +32,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "Util/BaseConfiguration.h" #include "Util/InputFileUtil.h" #include "Util/MachineInfo.h" +#include "Util/OpenMPWrapper.h" #include "Util/StringUtil.h" typedef BaseConfiguration ExtractorConfiguration; From 80add9f82032aa1b0b92b89af3ef0a328c6acd25 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 2 Jan 2013 00:33:39 +0100 Subject: [PATCH 015/161] Splitting monolithic extraction code into compile units --- Extractor/PBFParser.cpp | 509 ++++++++++++++++++++++++++++++++++++++++ Extractor/XMLParser.cpp | 290 +++++++++++++++++++++++ 2 files changed, 799 insertions(+) create mode 100644 Extractor/PBFParser.cpp create mode 100644 Extractor/XMLParser.cpp diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp new file mode 100644 index 000000000..4867fa194 --- /dev/null +++ b/Extractor/PBFParser.cpp @@ -0,0 +1,509 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU AFFERO General Public License as published by + the Free Software Foundation; either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + or see http://www.gnu.org/licenses/agpl.txt. + */ + +#include "PBFParser.h" + +PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){ + GOOGLE_PROTOBUF_VERIFY_VERSION; + //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? + //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. + threadDataQueue = boost::make_shared >( 2500 ); /* Max 2500 items in queue, hardcoded. */ + input.open(fileName, std::ios::in | std::ios::binary); + + if (!input) { + std::cerr << fileName << ": File not found." << std::endl; + } + +#ifndef NDEBUG + blockCount = 0; + groupCount = 0; +#endif +} + +void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) { + externalMemory = em; +} + +void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { + scriptingEnvironment = _se; +} + +PBFParser::~PBFParser() { + if(input.is_open()) + input.close(); + + // Clean up any leftover ThreadData objects in the queue + _ThreadData* td; + while (threadDataQueue->try_pop(td)) { + delete td; + } + google::protobuf::ShutdownProtobufLibrary(); + +#ifndef NDEBUG + DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups"); +#endif +} + +inline bool PBFParser::Init() { + _ThreadData initData; + /** read Header */ + if(!readPBFBlobHeader(input, &initData)) { + return false; + } + + if(readBlob(input, &initData)) { + if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) { + std::cerr << "[error] Header not parseable!" << std::endl; + return false; + } + + for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { + const std::string& feature = initData.PBFHeaderBlock.required_features( i ); + bool supported = false; + if ( "OsmSchema-V0.6" == feature ) + supported = true; + else if ( "DenseNodes" == feature ) + supported = true; + + if ( !supported ) { + std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; + return false; + } + } + } else { + std::cerr << "[error] blob not loaded!" << std::endl; + } + return true; +} + +inline void PBFParser::ReadData() { + bool keepRunning = true; + do { + _ThreadData *threadData = new _ThreadData(); + keepRunning = readNextBlock(input, threadData); + + if (keepRunning) + threadDataQueue->push(threadData); + else { + threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered + delete threadData; + } + } while(keepRunning); +} + +inline void PBFParser::ParseData() { + while (true) { + _ThreadData *threadData; + threadDataQueue->wait_and_pop(threadData); + if (threadData == NULL) { + INFO("Parse Data Thread Finished"); + threadDataQueue->push(NULL); // Signal end of data for other threads + break; + } + + loadBlock(threadData); + + for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) { + threadData->currentGroupID = i; + loadGroup(threadData); + + if(threadData->entityTypeIndicator == TypeNode) + parseNode(threadData); + if(threadData->entityTypeIndicator == TypeWay) + parseWay(threadData); + if(threadData->entityTypeIndicator == TypeRelation) + parseRelation(threadData); + if(threadData->entityTypeIndicator == TypeDenseNode) + parseDenseNode(threadData); + } + + delete threadData; + threadData = NULL; + } +} + +inline bool PBFParser::Parse() { + // Start the read and parse threads + boost::thread readThread(boost::bind(&PBFParser::ReadData, this)); + + //Open several parse threads that are synchronized before call to + boost::thread parseThread(boost::bind(&PBFParser::ParseData, this)); + + // Wait for the threads to finish + readThread.join(); + parseThread.join(); + + return true; +} + +inline void PBFParser::parseDenseNode(_ThreadData * threadData) { + const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense(); + int denseTagIndex = 0; + int m_lastDenseID = 0; + int m_lastDenseLatitude = 0; + int m_lastDenseLongitude = 0; + + ImportNode n; + std::vector nodesToParse; + for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { + n.Clear(); + m_lastDenseID += dense.id( i ); + m_lastDenseLatitude += dense.lat( i ); + m_lastDenseLongitude += dense.lon( i ); + n.id = m_lastDenseID; + n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; + n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; + while (denseTagIndex < dense.keys_vals_size()) { + const int tagValue = dense.keys_vals( denseTagIndex ); + if(tagValue == 0) { + ++denseTagIndex; + break; + } + const int keyValue = dense.keys_vals ( denseTagIndex+1 ); + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data(); + const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data(); + n.keyVals.Add(key, value); + denseTagIndex += 2; + } + nodesToParse.push_back(n); + } + + unsigned endi_nodes = nodesToParse.size(); +#pragma omp parallel for schedule ( guided ) + for(unsigned i = 0; i < endi_nodes; ++i) { + ImportNode &n = nodesToParse[i]; + /** Pass the unpacked node to the LUA call back **/ + try { + luabind::call_function( + scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), + "node_function", + boost::ref(n) + ); + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + // catch (...) { + // ERR("Unknown error occurred during PBF dense node parsing!"); + // } + } + + + BOOST_FOREACH(ImportNode &n, nodesToParse) { + if(!externalMemory->nodeFunction(n)) + std::cerr << "[PBFParser] dense node not parsed" << std::endl; + } +} + +inline void PBFParser::parseNode(_ThreadData * ) { + ERR("Parsing of simple nodes not supported. PBF should use dense nodes"); +} + +inline void PBFParser::parseRelation(_ThreadData * threadData) { + //TODO: leave early, if relatio is not a restriction + //TODO: reuse rawRestriction container + const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); + for(int i = 0; i < group.relations_size(); ++i ) { + const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); + bool isRestriction = false; + bool isOnlyRestriction = false; + for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) { + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); + const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); + if ("type" == key) { + if( "restriction" == val) + isRestriction = true; + else + break; + } + if ("restriction" == key) { + if(val.find("only_") == 0) + isOnlyRestriction = true; + } + + } + if(isRestriction) { + long long lastRef = 0; + _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); + for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { + std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); + lastRef += inputRelation.memids(rolesIndex); + + if(false == ("from" == role || "to" == role || "via" == role)) { + continue; + } + + switch(inputRelation.types(rolesIndex)) { + case 0: //node + if("from" == role || "to" == role) //Only via should be a node + continue; + assert("via" == role); + if(UINT_MAX != currentRestrictionContainer.viaNode) + currentRestrictionContainer.viaNode = UINT_MAX; + assert(UINT_MAX == currentRestrictionContainer.viaNode); + currentRestrictionContainer.restriction.viaNode = lastRef; + break; + case 1: //way + assert("from" == role || "to" == role || "via" == role); + if("from" == role) { + currentRestrictionContainer.fromWay = lastRef; + } + if ("to" == role) { + currentRestrictionContainer.toWay = lastRef; + } + if ("via" == role) { + assert(currentRestrictionContainer.restriction.toNode == UINT_MAX); + currentRestrictionContainer.viaNode = lastRef; + } + break; + case 2: //relation, not used. relations relating to relations are evil. + continue; + assert(false); + break; + + default: //should not happen + //cout << "unknown"; + assert(false); + break; + } + } + // if(UINT_MAX != currentRestriction.viaNode) { + // cout << "restr from " << currentRestriction.from << " via "; + // cout << "node " << currentRestriction.viaNode; + // cout << " to " << currentRestriction.to << endl; + // } + if(!externalMemory->restrictionFunction(currentRestrictionContainer)) + std::cerr << "[PBFParser] relation not parsed" << std::endl; + } + } +} + +inline void PBFParser::parseWay(_ThreadData * threadData) { + _Way w; + std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); + for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { + w.Clear(); + const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); + w.id = inputWay.id(); + unsigned pathNode(0); + for(int i = 0; i < inputWay.refs_size(); ++i) { + pathNode += inputWay.refs(i); + w.path.push_back(pathNode); + } + assert(inputWay.keys_size() == inputWay.vals_size()); + for(int i = 0; i < inputWay.keys_size(); ++i) { + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); + const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); + w.keyVals.Add(key, val); + } + + waysToParse.push_back(w); + } + + unsigned endi_ways = waysToParse.size(); +#pragma omp parallel for schedule ( guided ) + for(unsigned i = 0; i < endi_ways; ++i) { + _Way & w = waysToParse[i]; + /** Pass the unpacked way to the LUA call back **/ + try { + luabind::call_function( + scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), + "way_function", + boost::ref(w), + w.path.size() + ); + + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + // catch (...) { + // ERR("Unknown error!"); + // } + } + + BOOST_FOREACH(_Way & w, waysToParse) { + if(!externalMemory->wayFunction(w)) { + std::cerr << "[PBFParser] way not parsed" << std::endl; + } + } +} + +inline void PBFParser::loadGroup(_ThreadData * threadData) { +#ifndef NDEBUG + ++groupCount; +#endif + + const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); + threadData->entityTypeIndicator = 0; + if ( group.nodes_size() != 0 ) { + threadData->entityTypeIndicator = TypeNode; + } + if ( group.ways_size() != 0 ) { + threadData->entityTypeIndicator = TypeWay; + } + if ( group.relations_size() != 0 ) { + threadData->entityTypeIndicator = TypeRelation; + } + if ( group.has_dense() ) { + threadData->entityTypeIndicator = TypeDenseNode; + assert( group.dense().id_size() != 0 ); + } + assert( threadData->entityTypeIndicator != 0 ); +} + +inline void PBFParser::loadBlock(_ThreadData * threadData) { +#ifndef NDEBUG + ++blockCount; +#endif + threadData->currentGroupID = 0; + threadData->currentEntityID = 0; +} + +inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) { + int size(0); + stream.read((char *)&size, sizeof(int)); + size = swapEndian(size); + if(stream.eof()) { + return false; + } + if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) { + return false; + } + char *data = new char[size]; + stream.read(data, size*sizeof(data[0])); + + bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size); + delete[] data; + return dataSuccessfullyParsed; +} + +inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) { + unsigned rawSize = threadData->PBFBlob.raw_size(); + char* unpackedDataArray = new char[rawSize]; + z_stream compressedDataStream; + compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data(); + compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size(); + compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray; + compressedDataStream.avail_out = rawSize; + compressedDataStream.zalloc = Z_NULL; + compressedDataStream.zfree = Z_NULL; + compressedDataStream.opaque = Z_NULL; + int ret = inflateInit( &compressedDataStream ); + if ( ret != Z_OK ) { + std::cerr << "[error] failed to init zlib stream" << std::endl; + delete[] unpackedDataArray; + return false; + } + + ret = inflate( &compressedDataStream, Z_FINISH ); + if ( ret != Z_STREAM_END ) { + std::cerr << "[error] failed to inflate zlib stream" << std::endl; + std::cerr << "[error] Error type: " << ret << std::endl; + delete[] unpackedDataArray; + return false; + } + + ret = inflateEnd( &compressedDataStream ); + if ( ret != Z_OK ) { + std::cerr << "[error] failed to deinit zlib stream" << std::endl; + delete[] unpackedDataArray; + return false; + } + + threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize); + std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin()); + delete[] unpackedDataArray; + return true; +} + +inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) { + return false; +} + +inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) { + if(stream.eof()) + return false; + + const int size = threadData->PBFBlobHeader.datasize(); + if ( size < 0 || size > MAX_BLOB_SIZE ) { + std::cerr << "[error] invalid Blob size:" << size << std::endl; + return false; + } + + char* data = new char[size]; + stream.read(data, sizeof(data[0])*size); + + if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) { + std::cerr << "[error] failed to parse blob" << std::endl; + delete[] data; + return false; + } + + if ( threadData->PBFBlob.has_raw() ) { + const std::string& data = threadData->PBFBlob.raw(); + threadData->charBuffer.clear(); + threadData->charBuffer.resize( data.size() ); + std::copy(data.begin(), data.end(), threadData->charBuffer.begin()); + } else if ( threadData->PBFBlob.has_zlib_data() ) { + if ( !unpackZLIB(stream, threadData) ) { + std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl; + delete[] data; + return false; + } + } else if ( threadData->PBFBlob.has_lzma_data() ) { + if ( !unpackLZMA(stream, threadData) ) + std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; + delete[] data; + return false; + } else { + std::cerr << "[error] Blob contains no data" << std::endl; + delete[] data; + return false; + } + delete[] data; + return true; +} + +bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) { + if(stream.eof()) { + return false; + } + + if ( !readPBFBlobHeader(stream, threadData) ){ + return false; + } + + if ( threadData->PBFBlobHeader.type() != "OSMData" ) { + return false; + } + + if ( !readBlob(stream, threadData) ) { + return false; + } + + if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) { + ERR("failed to parse PrimitiveBlock"); + return false; + } + return true; +} diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp new file mode 100644 index 000000000..a2f645089 --- /dev/null +++ b/Extractor/XMLParser.cpp @@ -0,0 +1,290 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU AFFERO General Public License as published by + the Free Software Foundation; either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + or see http://www.gnu.org/licenses/agpl.txt. + */ + +#include + +#include "XMLParser.h" + +#include "ExtractorStructs.h" +#include "../DataStructures/HashTable.h" +#include "../DataStructures/InputReaderFactory.h" + + +XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){ + WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); + inputReader = inputReaderFactory(filename); +} + +XMLParser::~XMLParser() {} + +void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) { + externalMemory = em; +} + +void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { + myLuaState = _se.getLuaStateForThreadID(0); +} + +bool XMLParser::Init() { + return (xmlTextReaderRead( inputReader ) == 1); +} +bool XMLParser::Parse() { + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int type = xmlTextReaderNodeType( inputReader ); + + //1 is Element + if ( type != 1 ) + continue; + + xmlChar* currentName = xmlTextReaderName( inputReader ); + if ( currentName == NULL ) + continue; + + if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { + ImportNode n = _ReadXMLNode( ); + /** Pass the unpacked node to the LUA call back **/ + try { + luabind::call_function( + myLuaState, + "node_function", + boost::ref(n) + ); + if(!externalMemory->nodeFunction(n)) + std::cerr << "[XMLParser] dense node not parsed" << std::endl; + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + lua_State* Ler=er.state(); + report_errors(Ler, -1); + } catch (std::exception & e) { + ERR(e.what()); + } catch (...) { + ERR("Unknown error occurred during XML node parsing!"); + } + } + + if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { + _Way way = _ReadXMLWay( ); + + /** Pass the unpacked way to the LUA call back **/ + try { + luabind::call_function( + myLuaState, + "way_function", + boost::ref(way), + way.path.size() + ); + if(!externalMemory->wayFunction(way)) { + std::cerr << "[PBFParser] way not parsed" << std::endl; + } + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + lua_State* Ler=er.state(); + report_errors(Ler, -1); + } catch (std::exception & e) { + ERR(e.what()); + } catch (...) { + ERR("Unknown error occurred during XML way parsing!"); + } + } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { + _RawRestrictionContainer r = _ReadXMLRestriction(); + if(r.fromWay != UINT_MAX) { + if(!externalMemory->restrictionFunction(r)) { + std::cerr << "[XMLParser] restriction not parsed" << std::endl; + } + } + } + xmlFree( currentName ); + } + return true; +} + +_RawRestrictionContainer XMLParser::_ReadXMLRestriction() { + _RawRestrictionContainer restriction; + + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + if ( k != NULL && value != NULL ) { + if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ + if(0 == std::string((const char *) value).find("only_")) + restriction.restriction.flags.isOnly = true; + } + + } + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { + xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); + if ( ref != NULL ) { + xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); + xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); + if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { + restriction.toWay = atoi((const char*) ref); + } + if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { + restriction.fromWay = atoi((const char*) ref); + } + if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { + restriction.restriction.viaNode = atoi((const char*) ref); + } + + if(NULL != type) + xmlFree( type ); + if(NULL != role) + xmlFree( role ); + if(NULL != ref) + xmlFree( ref ); + } + } + xmlFree( childName ); + } + } + return restriction; +} + +_Way XMLParser::_ReadXMLWay() { + _Way way; + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader ); + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { + xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); + way.id = atoi((char*)id); + xmlFree(id); + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + // cout << "->k=" << k << ", v=" << value << endl; + if ( k != NULL && value != NULL ) { + + way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); + } + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { + xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); + if ( ref != NULL ) { + way.path.push_back( atoi(( const char* ) ref ) ); + xmlFree( ref ); + } + } + xmlFree( childName ); + } + } + return way; +} + +ImportNode XMLParser::_ReadXMLNode() { + ImportNode node; + + xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); + if ( attribute != NULL ) { + node.lat = static_cast(100000.*atof(( const char* ) attribute ) ); + xmlFree( attribute ); + } + attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); + if ( attribute != NULL ) { + node.lon = static_cast(100000.*atof(( const char* ) attribute )); + xmlFree( attribute ); + } + attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); + if ( attribute != NULL ) { + node.id = atoi(( const char* ) attribute ); + xmlFree( attribute ); + } + + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader ); + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + // 1 = Element, 15 = EndElement + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + if ( k != NULL && value != NULL ) { + node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); + } + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } + + xmlFree( childName ); + } + } + return node; +} \ No newline at end of file From 877865a4b11e828505261b6b03b5b643f5914e60 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 4 Jan 2013 12:22:09 +0100 Subject: [PATCH 016/161] removing profile --- profile.lua | 222 ---------------------------------------------------- 1 file changed, 222 deletions(-) delete mode 100644 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 100644 index b2291c1b0..000000000 --- a/profile.lua +++ /dev/null @@ -1,222 +0,0 @@ --- Begin of globals - -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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, ["forestery"] = true } -access_tag_restricted = { ["destination"] = true, ["delivery"] = true } -access_tags = { "motorcar", "motor_vehicle", "vehicle" } -access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } -service_tag_restricted = { ["parking_aisle"] = true } -ignore_in_grid = { ["ferry"] = true } - -speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, --- ["track"] = 5, - ["ferry"] = 5, - ["default"] = 50 -} - -take_minimum_of_speeds = false -obey_oneway = true -obey_bollards = true -use_restrictions = true -ignore_areas = true -- future feature -traffic_signal_penalty = 2 -u_turn_penalty = 20 - --- End of globals - ---find first tag in access hierachy which is set -local function find_access_tag(source) - for i,v in ipairs(access_tags_hierachy) do - if source.tags:Holds(v) then - local tag = source.tags:Find(v) - if tag ~= '' then --and tag ~= "" then - return tag - end - end - end - return nil -end - -local function find_in_keyvals(keyvals, tag) - if keyvals:Holds(tag) then - return keyvals:Find(tag) - else - return nil - end -end - -local function parse_maxspeed(source) - if source == nil then - return 0 - end - local n = tonumber(source) - if n == nil then - n = 0 - end - if string.match(source, "mph") or string.match(source, "mp/h") then - n = (n*1609)/1000; - end - return math.abs(n) -end - -function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = find_access_tag(node) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; - end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end - end - return 1 -end - - -function way_function (way, numberOfNodesInWay) - - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = find_access_tag(way) - - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name --- else --- way.name = highway -- if no name exists, use way type - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) - then - if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); - way.is_duration_set = true - end - way.direction = Way.bidirectional - if speed_profile[route] ~= nil then - highway = route; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) - end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end - - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end - - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel - - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 - return 1 -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 From 8ab591598331e4d663e952486366ea2acf176dba Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 4 Jan 2013 12:23:25 +0100 Subject: [PATCH 017/161] Add symlink to the profile in the respective folde --- profile.lua | 1 + 1 file changed, 1 insertion(+) create mode 120000 profile.lua diff --git a/profile.lua b/profile.lua new file mode 120000 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file From 7c54d4e62fc84b29915dc618fd3dba2962752e92 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 4 Jan 2013 12:31:43 +0100 Subject: [PATCH 018/161] Fixes the Birminingham speed limit bug reported by Philip Barnes --- profiles/car.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/profiles/car.lua b/profiles/car.lua index 1e2d6c379..4a633b4e3 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -64,13 +64,14 @@ local function parse_maxspeed(source) if source == nil then return 0 end - local n = tonumber(source) + local n = tonumber(source:match("%d*")) if n == nil then n = 0 end if string.match(source, "mph") or string.match(source, "mp/h") then n = (n*1609)/1000; end + io.write("speed: "..n.."\n") return math.abs(n) end From 4ac5440a4a77015d11fed9aaef4d8bfd65575339 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 4 Jan 2013 12:49:31 +0100 Subject: [PATCH 019/161] Removing debug output --- profiles/car.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/profiles/car.lua b/profiles/car.lua index 4a633b4e3..a3db99233 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -71,7 +71,6 @@ local function parse_maxspeed(source) if string.match(source, "mph") or string.match(source, "mp/h") then n = (n*1609)/1000; end - io.write("speed: "..n.."\n") return math.abs(n) end From 551af0e45ad0ceb2b036d9a4c6e7574a03d03d09 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 4 Jan 2013 16:09:00 +0100 Subject: [PATCH 020/161] fix a few restrictions tests --- features/bicycle/restrictions.feature | 4 ++-- features/car/restrictions.feature | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index 736c939aa..ccf3fe9c9 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -218,8 +218,8 @@ Feature: Bike - Turn restrictions | type | way:from | way:to | node:via | restriction | except | | restriction | sj | aj | j | no_left_turn | bicycle | | restriction | sj | bj | j | no_left_turn | | - | restriction | sj | cj | j | no_right_turn | bicycle | - | restriction | sj | dj | j | no_right_turn | | + | restriction | sj | cj | j | no_right_turn | | + | restriction | sj | dj | j | no_right_turn | bicycle | When I route I should get | from | to | route | diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature index 1ee527395..fc16917e8 100644 --- a/features/car/restrictions.feature +++ b/features/car/restrictions.feature @@ -218,8 +218,8 @@ Feature: Car - Turn restrictions | type | way:from | way:to | node:via | restriction | except | | restriction | sj | aj | j | no_left_turn | motorcar | | restriction | sj | bj | j | no_left_turn | | - | restriction | sj | cj | j | no_right_turn | motorcar | - | restriction | sj | dj | j | no_right_turn | | + | restriction | sj | cj | j | no_right_turn | | + | restriction | sj | dj | j | no_right_turn | motorcar | When I route I should get | from | to | route | From fa050ad6164d13d6e71a06c12cd644476c6df559 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 5 Jan 2013 17:27:10 +0100 Subject: [PATCH 021/161] Fixing registration of package path. --- Util/LuaUtil.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Util/LuaUtil.h b/Util/LuaUtil.h index f47869a8a..fadf78d6f 100644 --- a/Util/LuaUtil.h +++ b/Util/LuaUtil.h @@ -33,8 +33,7 @@ void LUA_print(T number) { } // Check if the lua function is defined -bool lua_function_exists(lua_State* lua_state, const char* name) -{ +inline bool lua_function_exists(lua_State* lua_state, const char* name) { luabind::object g = luabind::globals(lua_state); luabind::object func = g[name]; return func && (luabind::type(func) == LUA_TFUNCTION); @@ -42,13 +41,12 @@ bool lua_function_exists(lua_State* lua_state, const char* name) // Add the folder contain the script to the lua load path, so script can easily require() other lua scripts inside that folder, or subfolders. // See http://lua-users.org/wiki/PackagePath for details on the package.path syntax. -void luaAddScriptFolderToLoadPath(lua_State* myLuaState, const char* fileName) { +inline void luaAddScriptFolderToLoadPath(lua_State* myLuaState, const char* fileName) { const boost::filesystem::path profilePath( fileName ); - if( !profilePath.parent_path().empty() ) { - const std::string folder = profilePath.parent_path().string(); - const std::string luaCode = "package.path = \"" + folder + "/?.lua;\" .. package.path"; - luaL_dostring( myLuaState, luaCode.c_str() ); - } + std::string folder = profilePath.parent_path().string(); + //TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters + const std::string luaCode = "package.path = \"" + folder + "/?.lua;profiles/?.lua;\" .. package.path"; + luaL_dostring( myLuaState, luaCode.c_str() ); } #endif /* LUAUTIL_H_ */ From 64988ed8318e404a8d50223041daada9d2d9ae19 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 5 Jan 2013 17:32:39 +0100 Subject: [PATCH 022/161] Adding functionality for turn restriction exceptions to profile --- profile.lua | 210 ++++++++++++++++++++++++++++++++++++++++++- profiles/bicycle.lua | 7 +- profiles/car.lua | 27 ++---- profiles/foot.lua | 7 ++ 4 files changed, 229 insertions(+), 22 deletions(-) mode change 120000 => 100644 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 120000 index bad7e6bb5..000000000 --- a/profile.lua +++ /dev/null @@ -1 +0,0 @@ -profiles/car.lua \ No newline at end of file diff --git a/profile.lua b/profile.lua new file mode 100644 index 000000000..c078647f6 --- /dev/null +++ b/profile.lua @@ -0,0 +1,209 @@ +-- Begin of globals +require("lib/access") + +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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 } +access_tag_restricted = { ["destination"] = true, ["delivery"] = true } +access_tags = { "motorcar", "motor_vehicle", "vehicle" } +access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } +service_tag_restricted = { ["parking_aisle"] = true } +ignore_in_grid = { ["ferry"] = true } +restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } + +speed_profile = { + ["motorway"] = 90, + ["motorway_link"] = 75, + ["trunk"] = 85, + ["trunk_link"] = 70, + ["primary"] = 65, + ["primary_link"] = 60, + ["secondary"] = 55, + ["secondary_link"] = 50, + ["tertiary"] = 40, + ["tertiary_link"] = 30, + ["unclassified"] = 25, + ["residential"] = 25, + ["living_street"] = 10, + ["service"] = 15, +-- ["track"] = 5, + ["ferry"] = 5, + ["default"] = 50 +} + +take_minimum_of_speeds = false +obey_oneway = true +obey_bollards = true +use_restrictions = true +ignore_areas = true -- future feature +traffic_signal_penalty = 2 +u_turn_penalty = 20 + +-- End of globals + +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end + +local function parse_maxspeed(source) + if source == nil then + return 0 + end + local n = tonumber(source:match("%d*")) + if n == nil then + n = 0 + end + if string.match(source, "mph") or string.match(source, "mp/h") then + n = (n*1609)/1000; + end + return math.abs(n) +end + +function node_function (node) + local barrier = node.tags:Find ("barrier") + local access = Access.find_access_tag(node, access_tags_hierachy) + local traffic_signal = node.tags:Find("highway") + + --flag node if it carries a traffic light + + if traffic_signal == "traffic_signals" then + node.traffic_light = true; + end + + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + return + else + node.bollard = true + end + end + return 1 +end + + +function way_function (way, numberOfNodesInWay) + + -- A way must have two nodes or more + if(numberOfNodesInWay < 2) then + return 0; + end + + -- First, get the properties of each way that we come across + local highway = way.tags:Find("highway") + local name = way.tags:Find("name") + local ref = way.tags:Find("ref") + local junction = way.tags:Find("junction") + local route = way.tags:Find("route") + local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local barrier = way.tags:Find("barrier") + local oneway = way.tags:Find("oneway") + local cycleway = way.tags:Find("cycleway") + local duration = way.tags:Find("duration") + local service = way.tags:Find("service") + local area = way.tags:Find("area") + local access = Access.find_access_tag(way, access_tags_hierachy) + + -- Second, parse the way according to these properties + + if ignore_areas and ("yes" == area) then + return 0 + end + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] then + return 0 + end + + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name +-- else +-- way.name = highway -- if no name exists, use way type + end + + if "roundabout" == junction then + way.roundabout = true; + end + + -- Handling ferries and piers + if (speed_profile[route] ~= nil and speed_profile[route] > 0) + then + if durationIsValid(duration) then + way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); + way.is_duration_set = true + end + way.direction = Way.bidirectional + if speed_profile[route] ~= nil then + highway = route; + end + if not way.is_duration_set then + way.speed = speed_profile[highway] + end + end + + -- Set the avg speed on the way if it is accessible by road class + if (speed_profile[highway] ~= nil and way.speed == -1 ) then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile[highway], maxspeed) + end + + -- Set the avg speed on ways that are marked accessible + if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile["default"], maxspeed) + end + + -- Set access restriction flag if access is allowed under certain restrictions only + if access ~= "" and access_tag_restricted[access] then + way.is_access_restricted = true + end + + -- Set access restriction flag if service is allowed under certain restrictions only + if service ~= "" and service_tag_restricted[service] then + way.is_access_restricted = true + end + + -- Set direction according to tags on way + if obey_oneway then + if oneway == "no" or oneway == "0" or oneway == "false" then + way.direction = Way.bidirectional + elseif oneway == "-1" then + way.direction = Way.opposite + elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then + way.direction = Way.oneway + else + way.direction = Way.bidirectional + end + else + way.direction = Way.bidirectional + end + + -- Override general direction settings of there is a specific one for our mode of travel + + if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then + way.ignore_in_grid = true + end + way.type = 1 + return 1 +end + +-- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT + +function node_vector_function(vector) + for v in vector.nodes do + node_function(v) + end +end diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index f077aa1d6..6038126ee 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -8,6 +8,7 @@ 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" } default_speed = 16 @@ -70,7 +71,11 @@ u_turn_penalty = 20 -- End of globals ---find first tag in access hierachy which is set +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end function node_function (node) local barrier = node.tags:Find ("barrier") diff --git a/profiles/car.lua b/profiles/car.lua index a3db99233..c078647f6 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -1,4 +1,5 @@ -- Begin of globals +require("lib/access") barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true} access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } @@ -8,6 +9,7 @@ access_tags = { "motorcar", "motor_vehicle", "vehicle" } access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } service_tag_restricted = { ["parking_aisle"] = true } ignore_in_grid = { ["ferry"] = true } +restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } speed_profile = { ["motorway"] = 90, @@ -39,24 +41,9 @@ u_turn_penalty = 20 -- End of globals ---find first tag in access hierachy which is set -local function find_access_tag(source) - for i,v in ipairs(access_tags_hierachy) do - if source.tags:Holds(v) then - local tag = source.tags:Find(v) - if tag ~= '' then --and tag ~= "" then - return tag - end - end - end - return nil -end - -local function find_in_keyvals(keyvals, tag) - if keyvals:Holds(tag) then - return keyvals:Find(tag) - else - return nil +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) end end @@ -76,7 +63,7 @@ end function node_function (node) local barrier = node.tags:Find ("barrier") - local access = find_access_tag(node) + local access = Access.find_access_tag(node, access_tags_hierachy) local traffic_signal = node.tags:Find("highway") --flag node if it carries a traffic light @@ -121,7 +108,7 @@ function way_function (way, numberOfNodesInWay) local duration = way.tags:Find("duration") local service = way.tags:Find("service") local area = way.tags:Find("area") - local access = find_access_tag(way) + local access = Access.find_access_tag(way, access_tags_hierachy) -- Second, parse the way according to these properties diff --git a/profiles/foot.lua b/profiles/foot.lua index 596917aa5..3f689a2d1 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -9,6 +9,7 @@ access_tag_restricted = { ["destination"] = true, ["delivery"] = true } access_tags = { "foot" } service_tag_restricted = { ["parking_aisle"] = true } ignore_in_grid = { ["ferry"] = true } +restriction_exception_tags = { "foot" } speed_profile = { ["primary"] = 5, @@ -43,6 +44,12 @@ u_turn_penalty = 2 -- End of globals +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end + function node_function (node) local barrier = node.tags:Find ("barrier") local access = node.tags:Find ("access") From 5de2aa1cbf0c7b096cd05e68b4c607235527f3de Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 5 Jan 2013 17:35:50 +0100 Subject: [PATCH 023/161] fixing test and removing todo tag --- features/bicycle/restrictions.feature | 12 ++++++------ features/car/restrictions.feature | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index ccf3fe9c9..20ee13c44 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -198,7 +198,7 @@ Feature: Bike - Turn restrictions | s | n | sj,nj | | s | e | | - @except @todo + @except Scenario: Bike - Except tag and on no_ restrictions Given the node map | b | x | c | @@ -207,10 +207,10 @@ Feature: Bike - Turn restrictions And the ways | nodes | oneway | - | sj | yes | + | sj | no | | xj | -1 | | aj | -1 | - | bj | -1 | + | bj | no | | cj | -1 | | dj | -1 | @@ -228,7 +228,7 @@ Feature: Bike - Turn restrictions | s | c | | | s | d | sj,dj | - @except @todo + @except Scenario: Bike - Except tag and on only_ restrictions Given the node map | a | | b | @@ -238,8 +238,8 @@ Feature: Bike - Turn restrictions And the ways | nodes | oneway | | sj | yes | - | aj | -1 | - | bj | -1 | + | aj | no | + | bj | no | And the relations | type | way:from | way:to | node:via | restriction | except | diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature index fc16917e8..91ba29865 100644 --- a/features/car/restrictions.feature +++ b/features/car/restrictions.feature @@ -198,8 +198,8 @@ Feature: Car - Turn restrictions | s | n | sj,nj | | s | e | | - @except @todo - Scenario: Bike - Except tag and on no_ restrictions + @except + Scenario: Car - Except tag and on no_ restrictions Given the node map | b | x | c | | a | j | d | @@ -207,11 +207,11 @@ Feature: Car - Turn restrictions And the ways | nodes | oneway | - | sj | yes | + | sj | no | | xj | -1 | | aj | -1 | - | bj | -1 | - | cj | -1 | + | bj | no | + | cj | no | | dj | -1 | And the relations @@ -228,8 +228,8 @@ Feature: Car - Turn restrictions | s | c | | | s | d | sj,dj | - @except @todo - Scenario: Bike - Except tag and on only_ restrictions + @except + Scenario: Car - Except tag and on only_ restrictions Given the node map | a | | b | | | j | | @@ -238,8 +238,8 @@ Feature: Car - Turn restrictions And the ways | nodes | oneway | | sj | yes | - | aj | -1 | - | bj | -1 | + | aj | no | + | bj | no | And the relations | type | way:from | way:to | node:via | restriction | except | From ffdaa71086adfee1bd542160cf7f24812e4f2e5a Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 5 Jan 2013 19:20:25 +0100 Subject: [PATCH 024/161] Implementation of turn restriction exceptions --- Extractor/PBFParser.cpp | 883 +++++++++++++++-------------- Extractor/PBFParser.h | 2 + Extractor/ScriptingEnvironment.cpp | 40 +- Extractor/ScriptingEnvironment.h | 3 + Extractor/XMLParser.cpp | 523 +++++++++-------- Extractor/XMLParser.h | 2 + 6 files changed, 761 insertions(+), 692 deletions(-) diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 4867fa194..42a2571da 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -1,17 +1,17 @@ /* open source routing machine Copyright (C) Dennis Luxen, others 2010 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by the Free Software Foundation; either version 3 of the License, or any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -21,489 +21,524 @@ #include "PBFParser.h" PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){ - GOOGLE_PROTOBUF_VERIFY_VERSION; - //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? - //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. - threadDataQueue = boost::make_shared >( 2500 ); /* Max 2500 items in queue, hardcoded. */ - input.open(fileName, std::ios::in | std::ios::binary); - - if (!input) { - std::cerr << fileName << ": File not found." << std::endl; - } - + GOOGLE_PROTOBUF_VERIFY_VERSION; + //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? + //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. + threadDataQueue = boost::make_shared >( 2500 ); /* Max 2500 items in queue, hardcoded. */ + input.open(fileName, std::ios::in | std::ios::binary); + + if (!input) { + std::cerr << fileName << ": File not found." << std::endl; + } + #ifndef NDEBUG - blockCount = 0; - groupCount = 0; + blockCount = 0; + groupCount = 0; #endif } void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; + externalMemory = em; } void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - scriptingEnvironment = _se; + scriptingEnvironment = _se; + + if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) { + //get list of turn restriction exceptions + try { + luabind::call_function( + scriptingEnvironment.getLuaStateForThreadID(0), + "get_exceptions", + boost::ref(restriction_exceptions_vector) + ); + INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction"); + BOOST_FOREACH(std::string & str, restriction_exceptions_vector) { + INFO("ignoring: " << str); + } + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + } else { + INFO("Found no exceptions to turn restrictions"); + } } PBFParser::~PBFParser() { - if(input.is_open()) - input.close(); - - // Clean up any leftover ThreadData objects in the queue - _ThreadData* td; - while (threadDataQueue->try_pop(td)) { - delete td; - } - google::protobuf::ShutdownProtobufLibrary(); - + if(input.is_open()) + input.close(); + + // Clean up any leftover ThreadData objects in the queue + _ThreadData* td; + while (threadDataQueue->try_pop(td)) { + delete td; + } + google::protobuf::ShutdownProtobufLibrary(); + #ifndef NDEBUG - DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups"); + DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups"); #endif } inline bool PBFParser::Init() { - _ThreadData initData; - /** read Header */ - if(!readPBFBlobHeader(input, &initData)) { - return false; - } - - if(readBlob(input, &initData)) { - if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) { - std::cerr << "[error] Header not parseable!" << std::endl; - return false; - } - - for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { - const std::string& feature = initData.PBFHeaderBlock.required_features( i ); - bool supported = false; - if ( "OsmSchema-V0.6" == feature ) - supported = true; - else if ( "DenseNodes" == feature ) - supported = true; - - if ( !supported ) { - std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; - return false; - } - } - } else { - std::cerr << "[error] blob not loaded!" << std::endl; - } - return true; + _ThreadData initData; + /** read Header */ + if(!readPBFBlobHeader(input, &initData)) { + return false; + } + + if(readBlob(input, &initData)) { + if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) { + std::cerr << "[error] Header not parseable!" << std::endl; + return false; + } + + for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { + const std::string& feature = initData.PBFHeaderBlock.required_features( i ); + bool supported = false; + if ( "OsmSchema-V0.6" == feature ) + supported = true; + else if ( "DenseNodes" == feature ) + supported = true; + + if ( !supported ) { + std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; + return false; + } + } + } else { + std::cerr << "[error] blob not loaded!" << std::endl; + } + return true; } inline void PBFParser::ReadData() { - bool keepRunning = true; - do { - _ThreadData *threadData = new _ThreadData(); - keepRunning = readNextBlock(input, threadData); - - if (keepRunning) - threadDataQueue->push(threadData); - else { - threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered - delete threadData; - } - } while(keepRunning); + bool keepRunning = true; + do { + _ThreadData *threadData = new _ThreadData(); + keepRunning = readNextBlock(input, threadData); + + if (keepRunning) + threadDataQueue->push(threadData); + else { + threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered + delete threadData; + } + } while(keepRunning); } inline void PBFParser::ParseData() { - while (true) { - _ThreadData *threadData; - threadDataQueue->wait_and_pop(threadData); - if (threadData == NULL) { - INFO("Parse Data Thread Finished"); - threadDataQueue->push(NULL); // Signal end of data for other threads - break; - } - - loadBlock(threadData); - - for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) { - threadData->currentGroupID = i; - loadGroup(threadData); - - if(threadData->entityTypeIndicator == TypeNode) - parseNode(threadData); - if(threadData->entityTypeIndicator == TypeWay) - parseWay(threadData); - if(threadData->entityTypeIndicator == TypeRelation) - parseRelation(threadData); - if(threadData->entityTypeIndicator == TypeDenseNode) - parseDenseNode(threadData); - } - - delete threadData; - threadData = NULL; - } + while (true) { + _ThreadData *threadData; + threadDataQueue->wait_and_pop(threadData); + if (threadData == NULL) { + INFO("Parse Data Thread Finished"); + threadDataQueue->push(NULL); // Signal end of data for other threads + break; + } + + loadBlock(threadData); + + for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) { + threadData->currentGroupID = i; + loadGroup(threadData); + + if(threadData->entityTypeIndicator == TypeNode) + parseNode(threadData); + if(threadData->entityTypeIndicator == TypeWay) + parseWay(threadData); + if(threadData->entityTypeIndicator == TypeRelation) + parseRelation(threadData); + if(threadData->entityTypeIndicator == TypeDenseNode) + parseDenseNode(threadData); + } + + delete threadData; + threadData = NULL; + } } inline bool PBFParser::Parse() { - // Start the read and parse threads - boost::thread readThread(boost::bind(&PBFParser::ReadData, this)); - - //Open several parse threads that are synchronized before call to - boost::thread parseThread(boost::bind(&PBFParser::ParseData, this)); - - // Wait for the threads to finish - readThread.join(); - parseThread.join(); - - return true; + // Start the read and parse threads + boost::thread readThread(boost::bind(&PBFParser::ReadData, this)); + + //Open several parse threads that are synchronized before call to + boost::thread parseThread(boost::bind(&PBFParser::ParseData, this)); + + // Wait for the threads to finish + readThread.join(); + parseThread.join(); + + return true; } inline void PBFParser::parseDenseNode(_ThreadData * threadData) { - const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense(); - int denseTagIndex = 0; - int m_lastDenseID = 0; - int m_lastDenseLatitude = 0; - int m_lastDenseLongitude = 0; - - ImportNode n; - std::vector nodesToParse; - for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { - n.Clear(); - m_lastDenseID += dense.id( i ); - m_lastDenseLatitude += dense.lat( i ); - m_lastDenseLongitude += dense.lon( i ); - n.id = m_lastDenseID; - n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; - n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; - while (denseTagIndex < dense.keys_vals_size()) { - const int tagValue = dense.keys_vals( denseTagIndex ); - if(tagValue == 0) { - ++denseTagIndex; - break; - } - const int keyValue = dense.keys_vals ( denseTagIndex+1 ); - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data(); - const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data(); - n.keyVals.Add(key, value); - denseTagIndex += 2; - } - nodesToParse.push_back(n); - } - - unsigned endi_nodes = nodesToParse.size(); + const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense(); + int denseTagIndex = 0; + int m_lastDenseID = 0; + int m_lastDenseLatitude = 0; + int m_lastDenseLongitude = 0; + + ImportNode n; + std::vector nodesToParse; + for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { + n.Clear(); + m_lastDenseID += dense.id( i ); + m_lastDenseLatitude += dense.lat( i ); + m_lastDenseLongitude += dense.lon( i ); + n.id = m_lastDenseID; + n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; + n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; + while (denseTagIndex < dense.keys_vals_size()) { + const int tagValue = dense.keys_vals( denseTagIndex ); + if(tagValue == 0) { + ++denseTagIndex; + break; + } + const int keyValue = dense.keys_vals ( denseTagIndex+1 ); + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data(); + const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data(); + n.keyVals.Add(key, value); + denseTagIndex += 2; + } + nodesToParse.push_back(n); + } + + unsigned endi_nodes = nodesToParse.size(); #pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_nodes; ++i) { - ImportNode &n = nodesToParse[i]; - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "node_function", - boost::ref(n) - ); - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - // catch (...) { - // ERR("Unknown error occurred during PBF dense node parsing!"); - // } - } - - - BOOST_FOREACH(ImportNode &n, nodesToParse) { - if(!externalMemory->nodeFunction(n)) - std::cerr << "[PBFParser] dense node not parsed" << std::endl; - } + for(unsigned i = 0; i < endi_nodes; ++i) { + ImportNode &n = nodesToParse[i]; + /** Pass the unpacked node to the LUA call back **/ + try { + luabind::call_function( + scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), + "node_function", + boost::ref(n) + ); + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + // catch (...) { + // ERR("Unknown error occurred during PBF dense node parsing!"); + // } + } + + + BOOST_FOREACH(ImportNode &n, nodesToParse) { + if(!externalMemory->nodeFunction(n)) + std::cerr << "[PBFParser] dense node not parsed" << std::endl; + } } inline void PBFParser::parseNode(_ThreadData * ) { - ERR("Parsing of simple nodes not supported. PBF should use dense nodes"); + ERR("Parsing of simple nodes not supported. PBF should use dense nodes"); } inline void PBFParser::parseRelation(_ThreadData * threadData) { - //TODO: leave early, if relatio is not a restriction - //TODO: reuse rawRestriction container - const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); - for(int i = 0; i < group.relations_size(); ++i ) { - const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); - bool isRestriction = false; - bool isOnlyRestriction = false; - for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) { - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); - const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); - if ("type" == key) { - if( "restriction" == val) - isRestriction = true; - else - break; - } - if ("restriction" == key) { - if(val.find("only_") == 0) - isOnlyRestriction = true; - } - - } - if(isRestriction) { - long long lastRef = 0; - _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); - for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { - std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); - lastRef += inputRelation.memids(rolesIndex); - - if(false == ("from" == role || "to" == role || "via" == role)) { - continue; - } - - switch(inputRelation.types(rolesIndex)) { - case 0: //node - if("from" == role || "to" == role) //Only via should be a node - continue; - assert("via" == role); - if(UINT_MAX != currentRestrictionContainer.viaNode) - currentRestrictionContainer.viaNode = UINT_MAX; - assert(UINT_MAX == currentRestrictionContainer.viaNode); - currentRestrictionContainer.restriction.viaNode = lastRef; - break; - case 1: //way - assert("from" == role || "to" == role || "via" == role); - if("from" == role) { - currentRestrictionContainer.fromWay = lastRef; - } - if ("to" == role) { - currentRestrictionContainer.toWay = lastRef; - } - if ("via" == role) { - assert(currentRestrictionContainer.restriction.toNode == UINT_MAX); - currentRestrictionContainer.viaNode = lastRef; - } - break; - case 2: //relation, not used. relations relating to relations are evil. - continue; - assert(false); - break; - - default: //should not happen - //cout << "unknown"; - assert(false); - break; - } - } - // if(UINT_MAX != currentRestriction.viaNode) { - // cout << "restr from " << currentRestriction.from << " via "; - // cout << "node " << currentRestriction.viaNode; - // cout << " to " << currentRestriction.to << endl; - // } - if(!externalMemory->restrictionFunction(currentRestrictionContainer)) - std::cerr << "[PBFParser] relation not parsed" << std::endl; - } - } + //TODO: leave early, if relation is not a restriction + //TODO: reuse rawRestriction container + const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); + for(int i = 0; i < group.relations_size(); ++i ) { + std::string exception_of_restriction_tag; + const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); + bool isRestriction = false; + bool isOnlyRestriction = false; + for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) { + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); + const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); + if ("type" == key) { + if( "restriction" == val) + isRestriction = true; + else + break; + } + if ("restriction" == key) { + if(val.find("only_") == 0) + isOnlyRestriction = true; + } + if ("except" == key) { + exception_of_restriction_tag = val; + } + } + + //Check if restriction shall be ignored + if(isRestriction && ("" != exception_of_restriction_tag) ) { + //Be warned, this is quadratic work here, but we assume that + //only a few exceptions are actually defined. + std::vector tokenized_exception_tags_of_restriction; + boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*")); + BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) { + if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) { + isRestriction = false; + break; //BOOST_FOREACH + } + } + } + + + if(isRestriction) { + long long lastRef = 0; + _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); + for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { + std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); + lastRef += inputRelation.memids(rolesIndex); + + if(!("from" == role || "to" == role || "via" == role)) { + continue; + } + + switch(inputRelation.types(rolesIndex)) { + case 0: //node + if("from" == role || "to" == role) //Only via should be a node + continue; + assert("via" == role); + if(UINT_MAX != currentRestrictionContainer.viaNode) + currentRestrictionContainer.viaNode = UINT_MAX; + assert(UINT_MAX == currentRestrictionContainer.viaNode); + currentRestrictionContainer.restriction.viaNode = lastRef; + break; + case 1: //way + assert("from" == role || "to" == role || "via" == role); + if("from" == role) { + currentRestrictionContainer.fromWay = lastRef; + } + if ("to" == role) { + currentRestrictionContainer.toWay = lastRef; + } + if ("via" == role) { + assert(currentRestrictionContainer.restriction.toNode == UINT_MAX); + currentRestrictionContainer.viaNode = lastRef; + } + break; + case 2: //relation, not used. relations relating to relations are evil. + continue; + assert(false); + break; + + default: //should not happen + //cout << "unknown"; + assert(false); + break; + } + } + if(!externalMemory->restrictionFunction(currentRestrictionContainer)) + std::cerr << "[PBFParser] relation not parsed" << std::endl; + } + } } inline void PBFParser::parseWay(_ThreadData * threadData) { - _Way w; - std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); - for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { - w.Clear(); - const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); - w.id = inputWay.id(); - unsigned pathNode(0); - for(int i = 0; i < inputWay.refs_size(); ++i) { - pathNode += inputWay.refs(i); - w.path.push_back(pathNode); - } - assert(inputWay.keys_size() == inputWay.vals_size()); - for(int i = 0; i < inputWay.keys_size(); ++i) { - const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); - const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); - w.keyVals.Add(key, val); - } - - waysToParse.push_back(w); - } - - unsigned endi_ways = waysToParse.size(); + _Way w; + std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); + for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { + w.Clear(); + const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); + w.id = inputWay.id(); + unsigned pathNode(0); + for(int i = 0; i < inputWay.refs_size(); ++i) { + pathNode += inputWay.refs(i); + w.path.push_back(pathNode); + } + assert(inputWay.keys_size() == inputWay.vals_size()); + for(int i = 0; i < inputWay.keys_size(); ++i) { + const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); + const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); + w.keyVals.Add(key, val); + } + + waysToParse.push_back(w); + } + + unsigned endi_ways = waysToParse.size(); #pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_ways; ++i) { - _Way & w = waysToParse[i]; - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "way_function", - boost::ref(w), - w.path.size() - ); - - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - // catch (...) { - // ERR("Unknown error!"); - // } - } - - BOOST_FOREACH(_Way & w, waysToParse) { - if(!externalMemory->wayFunction(w)) { - std::cerr << "[PBFParser] way not parsed" << std::endl; - } - } + for(unsigned i = 0; i < endi_ways; ++i) { + _Way & w = waysToParse[i]; + /** Pass the unpacked way to the LUA call back **/ + try { + luabind::call_function( + scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), + "way_function", + boost::ref(w), + w.path.size() + ); + + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + // catch (...) { + // ERR("Unknown error!"); + // } + } + + BOOST_FOREACH(_Way & w, waysToParse) { + if(!externalMemory->wayFunction(w)) { + std::cerr << "[PBFParser] way not parsed" << std::endl; + } + } } inline void PBFParser::loadGroup(_ThreadData * threadData) { #ifndef NDEBUG - ++groupCount; + ++groupCount; #endif - - const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); - threadData->entityTypeIndicator = 0; - if ( group.nodes_size() != 0 ) { - threadData->entityTypeIndicator = TypeNode; - } - if ( group.ways_size() != 0 ) { - threadData->entityTypeIndicator = TypeWay; - } - if ( group.relations_size() != 0 ) { - threadData->entityTypeIndicator = TypeRelation; - } - if ( group.has_dense() ) { - threadData->entityTypeIndicator = TypeDenseNode; - assert( group.dense().id_size() != 0 ); - } - assert( threadData->entityTypeIndicator != 0 ); + + const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); + threadData->entityTypeIndicator = 0; + if ( group.nodes_size() != 0 ) { + threadData->entityTypeIndicator = TypeNode; + } + if ( group.ways_size() != 0 ) { + threadData->entityTypeIndicator = TypeWay; + } + if ( group.relations_size() != 0 ) { + threadData->entityTypeIndicator = TypeRelation; + } + if ( group.has_dense() ) { + threadData->entityTypeIndicator = TypeDenseNode; + assert( group.dense().id_size() != 0 ); + } + assert( threadData->entityTypeIndicator != 0 ); } inline void PBFParser::loadBlock(_ThreadData * threadData) { #ifndef NDEBUG - ++blockCount; + ++blockCount; #endif - threadData->currentGroupID = 0; - threadData->currentEntityID = 0; + threadData->currentGroupID = 0; + threadData->currentEntityID = 0; } inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) { - int size(0); - stream.read((char *)&size, sizeof(int)); - size = swapEndian(size); - if(stream.eof()) { - return false; - } - if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) { - return false; - } - char *data = new char[size]; - stream.read(data, size*sizeof(data[0])); - - bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size); - delete[] data; - return dataSuccessfullyParsed; + int size(0); + stream.read((char *)&size, sizeof(int)); + size = swapEndian(size); + if(stream.eof()) { + return false; + } + if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) { + return false; + } + char *data = new char[size]; + stream.read(data, size*sizeof(data[0])); + + bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size); + delete[] data; + return dataSuccessfullyParsed; } inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) { - unsigned rawSize = threadData->PBFBlob.raw_size(); - char* unpackedDataArray = new char[rawSize]; - z_stream compressedDataStream; - compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data(); - compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size(); - compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray; - compressedDataStream.avail_out = rawSize; - compressedDataStream.zalloc = Z_NULL; - compressedDataStream.zfree = Z_NULL; - compressedDataStream.opaque = Z_NULL; - int ret = inflateInit( &compressedDataStream ); - if ( ret != Z_OK ) { - std::cerr << "[error] failed to init zlib stream" << std::endl; - delete[] unpackedDataArray; - return false; - } - - ret = inflate( &compressedDataStream, Z_FINISH ); - if ( ret != Z_STREAM_END ) { - std::cerr << "[error] failed to inflate zlib stream" << std::endl; - std::cerr << "[error] Error type: " << ret << std::endl; - delete[] unpackedDataArray; - return false; - } - - ret = inflateEnd( &compressedDataStream ); - if ( ret != Z_OK ) { - std::cerr << "[error] failed to deinit zlib stream" << std::endl; - delete[] unpackedDataArray; - return false; - } - - threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize); - std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin()); - delete[] unpackedDataArray; - return true; + unsigned rawSize = threadData->PBFBlob.raw_size(); + char* unpackedDataArray = new char[rawSize]; + z_stream compressedDataStream; + compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data(); + compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size(); + compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray; + compressedDataStream.avail_out = rawSize; + compressedDataStream.zalloc = Z_NULL; + compressedDataStream.zfree = Z_NULL; + compressedDataStream.opaque = Z_NULL; + int ret = inflateInit( &compressedDataStream ); + if ( ret != Z_OK ) { + std::cerr << "[error] failed to init zlib stream" << std::endl; + delete[] unpackedDataArray; + return false; + } + + ret = inflate( &compressedDataStream, Z_FINISH ); + if ( ret != Z_STREAM_END ) { + std::cerr << "[error] failed to inflate zlib stream" << std::endl; + std::cerr << "[error] Error type: " << ret << std::endl; + delete[] unpackedDataArray; + return false; + } + + ret = inflateEnd( &compressedDataStream ); + if ( ret != Z_OK ) { + std::cerr << "[error] failed to deinit zlib stream" << std::endl; + delete[] unpackedDataArray; + return false; + } + + threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize); + std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin()); + delete[] unpackedDataArray; + return true; } inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) { - return false; + return false; } inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) { - if(stream.eof()) - return false; - - const int size = threadData->PBFBlobHeader.datasize(); - if ( size < 0 || size > MAX_BLOB_SIZE ) { - std::cerr << "[error] invalid Blob size:" << size << std::endl; - return false; - } - - char* data = new char[size]; - stream.read(data, sizeof(data[0])*size); - - if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) { - std::cerr << "[error] failed to parse blob" << std::endl; - delete[] data; - return false; - } - - if ( threadData->PBFBlob.has_raw() ) { - const std::string& data = threadData->PBFBlob.raw(); - threadData->charBuffer.clear(); - threadData->charBuffer.resize( data.size() ); - std::copy(data.begin(), data.end(), threadData->charBuffer.begin()); - } else if ( threadData->PBFBlob.has_zlib_data() ) { - if ( !unpackZLIB(stream, threadData) ) { - std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl; - delete[] data; - return false; - } - } else if ( threadData->PBFBlob.has_lzma_data() ) { - if ( !unpackLZMA(stream, threadData) ) - std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; - delete[] data; - return false; - } else { - std::cerr << "[error] Blob contains no data" << std::endl; - delete[] data; - return false; - } - delete[] data; - return true; + if(stream.eof()) + return false; + + const int size = threadData->PBFBlobHeader.datasize(); + if ( size < 0 || size > MAX_BLOB_SIZE ) { + std::cerr << "[error] invalid Blob size:" << size << std::endl; + return false; + } + + char* data = new char[size]; + stream.read(data, sizeof(data[0])*size); + + if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) { + std::cerr << "[error] failed to parse blob" << std::endl; + delete[] data; + return false; + } + + if ( threadData->PBFBlob.has_raw() ) { + const std::string& data = threadData->PBFBlob.raw(); + threadData->charBuffer.clear(); + threadData->charBuffer.resize( data.size() ); + std::copy(data.begin(), data.end(), threadData->charBuffer.begin()); + } else if ( threadData->PBFBlob.has_zlib_data() ) { + if ( !unpackZLIB(stream, threadData) ) { + std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl; + delete[] data; + return false; + } + } else if ( threadData->PBFBlob.has_lzma_data() ) { + if ( !unpackLZMA(stream, threadData) ) + std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; + delete[] data; + return false; + } else { + std::cerr << "[error] Blob contains no data" << std::endl; + delete[] data; + return false; + } + delete[] data; + return true; } bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) { - if(stream.eof()) { - return false; - } - - if ( !readPBFBlobHeader(stream, threadData) ){ - return false; - } - - if ( threadData->PBFBlobHeader.type() != "OSMData" ) { - return false; - } - - if ( !readBlob(stream, threadData) ) { - return false; - } - - if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) { - ERR("failed to parse PrimitiveBlock"); - return false; - } - return true; + if(stream.eof()) { + return false; + } + + if ( !readPBFBlobHeader(stream, threadData) ){ + return false; + } + + if ( threadData->PBFBlobHeader.type() != "OSMData" ) { + return false; + } + + if ( !readBlob(stream, threadData) ) { + return false; + } + + if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) { + ERR("failed to parse PrimitiveBlock"); + return false; + } + return true; } diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index be6920d8c..ed469272d 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -106,6 +106,8 @@ private: /* ThreadData Queue */ boost::shared_ptr > threadDataQueue; ScriptingEnvironment scriptingEnvironment; + + std::vector restriction_exceptions_vector; }; #endif /* PBFPARSER_H_ */ diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 2ef215cd1..9c461bcd7 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -18,16 +18,7 @@ or see http://www.gnu.org/licenses/agpl.txt. */ -extern "C" { -#include -#include -#include -} - #include "ScriptingEnvironment.h" -#include "../typedefs.h" -#include "../Util/LuaUtil.h" -#include "../Util/OpenMPWrapper.h" ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { @@ -45,6 +36,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { //open utility libraries string library; luaL_openlibs(myLuaState); + luaAddScriptFolderToLoadPath( myLuaState, fileName ); + // Add our function to the state's global scope luabind::module(myLuaState) [ luabind::def("print", LUA_print), @@ -53,17 +46,6 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::def("parseDuration", parseDuration) ]; - luaAddScriptFolderToLoadPath( myLuaState, fileName ); - -//#pragma omp critical -// { -// if(0 != luaL_dostring( -// myLuaState, -// "print('Initializing LUA engine')\n" -// )) { -// ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); -// } -// } luabind::module(myLuaState) [ luabind::class_ >("keyVals") .def("Add", &HashTable::Add) @@ -96,13 +78,17 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { .def_readwrite("tags", &_Way::keyVals) .def_readwrite("direction", &_Way::direction) .enum_("constants") - [ - luabind::value("notSure", 0), - luabind::value("oneway", 1), - luabind::value("bidirectional", 2), - luabind::value("opposite", 3) - ] - ]; + [ + luabind::value("notSure", 0), + luabind::value("oneway", 1), + luabind::value("bidirectional", 2), + luabind::value("opposite", 3) + ] + ]; + luabind::module(myLuaState) [ + luabind::class_ >("vector") + .def("Add", &std::vector::push_back) + ]; // Now call our function in a lua script //#pragma omp critical diff --git a/Extractor/ScriptingEnvironment.h b/Extractor/ScriptingEnvironment.h index 40f389878..015ff2529 100644 --- a/Extractor/ScriptingEnvironment.h +++ b/Extractor/ScriptingEnvironment.h @@ -31,7 +31,10 @@ extern "C" { #include "ExtractionHelperFunctions.h" #include "ExtractorStructs.h" +#include "../typedefs.h" #include "../DataStructures/ImportNode.h" +#include "../Util/LuaUtil.h" +#include "../Util/OpenMPWrapper.h" class ScriptingEnvironment { public: diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index a2f645089..47506b736 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -1,17 +1,17 @@ /* open source routing machine Copyright (C) Dennis Luxen, others 2010 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by the Free Software Foundation; either version 3 of the License, or any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -28,263 +28,304 @@ XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){ - WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); - inputReader = inputReaderFactory(filename); + WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); + inputReader = inputReaderFactory(filename); } XMLParser::~XMLParser() {} void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; + externalMemory = em; } void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - myLuaState = _se.getLuaStateForThreadID(0); + myLuaState = _se.getLuaStateForThreadID(0); + if(lua_function_exists(myLuaState, "get_exceptions" )) { + //get list of turn restriction exceptions + try { + luabind::call_function( + myLuaState, + "get_exceptions", + boost::ref(restriction_exceptions_vector) + ); + INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction"); + BOOST_FOREACH(std::string & str, restriction_exceptions_vector) { + INFO(" " << str); + } + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + } else { + INFO("Found no exceptions to turn restrictions"); + } } bool XMLParser::Init() { - return (xmlTextReaderRead( inputReader ) == 1); + return (xmlTextReaderRead( inputReader ) == 1); } bool XMLParser::Parse() { - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int type = xmlTextReaderNodeType( inputReader ); - - //1 is Element - if ( type != 1 ) - continue; - - xmlChar* currentName = xmlTextReaderName( inputReader ); - if ( currentName == NULL ) - continue; - - if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { - ImportNode n = _ReadXMLNode( ); - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "node_function", - boost::ref(n) - ); - if(!externalMemory->nodeFunction(n)) - std::cerr << "[XMLParser] dense node not parsed" << std::endl; - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML node parsing!"); - } - } - - if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - _Way way = _ReadXMLWay( ); - - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "way_function", - boost::ref(way), - way.path.size() - ); - if(!externalMemory->wayFunction(way)) { - std::cerr << "[PBFParser] way not parsed" << std::endl; - } - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML way parsing!"); - } - } - if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { - _RawRestrictionContainer r = _ReadXMLRestriction(); - if(r.fromWay != UINT_MAX) { - if(!externalMemory->restrictionFunction(r)) { - std::cerr << "[XMLParser] restriction not parsed" << std::endl; - } - } - } - xmlFree( currentName ); - } - return true; + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int type = xmlTextReaderNodeType( inputReader ); + + //1 is Element + if ( type != 1 ) + continue; + + xmlChar* currentName = xmlTextReaderName( inputReader ); + if ( currentName == NULL ) + continue; + + if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { + ImportNode n = _ReadXMLNode( ); + /** Pass the unpacked node to the LUA call back **/ + try { + luabind::call_function( + myLuaState, + "node_function", + boost::ref(n) + ); + if(!externalMemory->nodeFunction(n)) + std::cerr << "[XMLParser] dense node not parsed" << std::endl; + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + lua_State* Ler=er.state(); + report_errors(Ler, -1); + } catch (std::exception & e) { + ERR(e.what()); + } catch (...) { + ERR("Unknown error occurred during XML node parsing!"); + } + } + + if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { + _Way way = _ReadXMLWay( ); + + /** Pass the unpacked way to the LUA call back **/ + try { + luabind::call_function( + myLuaState, + "way_function", + boost::ref(way), + way.path.size() + ); + if(!externalMemory->wayFunction(way)) { + std::cerr << "[PBFParser] way not parsed" << std::endl; + } + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + lua_State* Ler=er.state(); + report_errors(Ler, -1); + } catch (std::exception & e) { + ERR(e.what()); + } catch (...) { + ERR("Unknown error occurred during XML way parsing!"); + } + } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { + _RawRestrictionContainer r = _ReadXMLRestriction(); + if(r.fromWay != UINT_MAX) { + if(!externalMemory->restrictionFunction(r)) { + std::cerr << "[XMLParser] restriction not parsed" << std::endl; + } + } + } + xmlFree( currentName ); + } + return true; } _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { - _RawRestrictionContainer restriction; - - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - if ( k != NULL && value != NULL ) { - if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ - if(0 == std::string((const char *) value).find("only_")) - restriction.restriction.flags.isOnly = true; - } - - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { - xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); - if ( ref != NULL ) { - xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); - xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); - if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { - restriction.toWay = atoi((const char*) ref); - } - if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { - restriction.fromWay = atoi((const char*) ref); - } - if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { - restriction.restriction.viaNode = atoi((const char*) ref); - } - - if(NULL != type) - xmlFree( type ); - if(NULL != role) - xmlFree( role ); - if(NULL != ref) - xmlFree( ref ); - } - } - xmlFree( childName ); - } - } - return restriction; + _RawRestrictionContainer restriction; + std::string exception_of_restriction_tag; + bool restriction_is_excepted = false; + + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + if ( k != NULL && value != NULL ) { + if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ + if(0 == std::string((const char *) value).find("only_")) + restriction.restriction.flags.isOnly = true; + } + } + if ( xmlStrEqual(k, (const xmlChar *) "except") ) { + exception_of_restriction_tag = (const char*) value; + } + + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { + xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); + if ( ref != NULL ) { + xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); + xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); + + if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { + restriction.toWay = atoi((const char*) ref); + } + if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { + restriction.fromWay = atoi((const char*) ref); + } + if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { + restriction.restriction.viaNode = atoi((const char*) ref); + } + + if(NULL != type) + xmlFree( type ); + if(NULL != role) + xmlFree( role ); + if(NULL != ref) + xmlFree( ref ); + } + } + xmlFree( childName ); + } + } + + //Check if restriction shall be ignored + if( "" != exception_of_restriction_tag ) { + //Be warned, this is quadratic work here, but we assume that + //only a few exceptions are actually defined. + std::vector tokenized_exception_tags_of_restriction; + boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*")); + BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) { + if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) { + restriction.fromWay = UINT_MAX; //workaround to ignore the restriction + break; //BOOST_FOREACH + } + } + } + + return restriction; } _Way XMLParser::_ReadXMLWay() { - _Way way; - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader ); - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { - xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); - way.id = atoi((char*)id); - xmlFree(id); - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - // cout << "->k=" << k << ", v=" << value << endl; - if ( k != NULL && value != NULL ) { - - way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { - xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); - if ( ref != NULL ) { - way.path.push_back( atoi(( const char* ) ref ) ); - xmlFree( ref ); - } - } - xmlFree( childName ); - } - } - return way; + _Way way; + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader ); + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { + xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); + way.id = atoi((char*)id); + xmlFree(id); + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + // cout << "->k=" << k << ", v=" << value << endl; + if ( k != NULL && value != NULL ) { + + way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); + } + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { + xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); + if ( ref != NULL ) { + way.path.push_back( atoi(( const char* ) ref ) ); + xmlFree( ref ); + } + } + xmlFree( childName ); + } + } + return way; } ImportNode XMLParser::_ReadXMLNode() { - ImportNode node; - - xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); - if ( attribute != NULL ) { - node.lat = static_cast(100000.*atof(( const char* ) attribute ) ); - xmlFree( attribute ); - } - attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); - if ( attribute != NULL ) { - node.lon = static_cast(100000.*atof(( const char* ) attribute )); - xmlFree( attribute ); - } - attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); - if ( attribute != NULL ) { - node.id = atoi(( const char* ) attribute ); - xmlFree( attribute ); - } - - if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { - const int depth = xmlTextReaderDepth( inputReader ); - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int childType = xmlTextReaderNodeType( inputReader ); - // 1 = Element, 15 = EndElement - if ( childType != 1 && childType != 15 ) - continue; - const int childDepth = xmlTextReaderDepth( inputReader ); - xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) - continue; - - if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { - xmlFree( childName ); - break; - } - if ( childType != 1 ) { - xmlFree( childName ); - continue; - } - - if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { - xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); - xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - if ( k != NULL && value != NULL ) { - node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); - } - if ( k != NULL ) - xmlFree( k ); - if ( value != NULL ) - xmlFree( value ); - } - - xmlFree( childName ); - } - } - return node; -} \ No newline at end of file + ImportNode node; + + xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); + if ( attribute != NULL ) { + node.lat = static_cast(100000.*atof(( const char* ) attribute ) ); + xmlFree( attribute ); + } + attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); + if ( attribute != NULL ) { + node.lon = static_cast(100000.*atof(( const char* ) attribute )); + xmlFree( attribute ); + } + attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); + if ( attribute != NULL ) { + node.id = atoi(( const char* ) attribute ); + xmlFree( attribute ); + } + + if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { + const int depth = xmlTextReaderDepth( inputReader ); + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int childType = xmlTextReaderNodeType( inputReader ); + // 1 = Element, 15 = EndElement + if ( childType != 1 && childType != 15 ) + continue; + const int childDepth = xmlTextReaderDepth( inputReader ); + xmlChar* childName = xmlTextReaderName( inputReader ); + if ( childName == NULL ) + continue; + + if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { + xmlFree( childName ); + break; + } + if ( childType != 1 ) { + xmlFree( childName ); + continue; + } + + if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { + xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); + xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); + if ( k != NULL && value != NULL ) { + node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); + } + if ( k != NULL ) + xmlFree( k ); + if ( value != NULL ) + xmlFree( value ); + } + + xmlFree( childName ); + } + } + return node; +} diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index f80ad48bc..d87c50145 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -45,6 +45,8 @@ private: xmlTextReaderPtr inputReader; ExtractorCallbacks * externalMemory; lua_State *myLuaState; + + std::vector restriction_exceptions_vector; }; #endif /* XMLPARSER_H_ */ From 00168cb12fefe0b9b80ce4a958356815506cb857 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 5 Jan 2013 22:47:12 +0100 Subject: [PATCH 025/161] Removing dead code. --- Extractor/ScriptingEnvironment.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 9c461bcd7..c2f42d79d 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -90,11 +90,6 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { .def("Add", &std::vector::push_back) ]; - // Now call our function in a lua script -//#pragma omp critical -// { -// INFO("Parsing speedprofile from " << fileName ); -// } if(0 != luaL_dofile(myLuaState, fileName) ) { ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); } From 565b0e97d10bbc44f593478bc8e315ba016fee0f Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 4 Jan 2013 19:03:15 +0100 Subject: [PATCH 026/161] rename @weight test to @fastest --- features/testbot/distance.feature | 4 ++-- features/testbot/{weight.feature => fastest.feature} | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename features/testbot/{weight.feature => fastest.feature} (84%) diff --git a/features/testbot/distance.feature b/features/testbot/distance.feature index ac1f38364..1fb436bc6 100644 --- a/features/testbot/distance.feature +++ b/features/testbot/distance.feature @@ -29,7 +29,7 @@ Feature: Distance calculation When I route I should get | from | to | route | distance | - | a | d | abcde | 300m +-8 | + | a | d | abcde | 300m +-2 | Scenario: Distance should equal sum of segments, rightwinded Given the node map @@ -43,7 +43,7 @@ Feature: Distance calculation When I route I should get | from | to | route | distance | - | a | d | abcde | 300m +-8 | + | a | d | abcde | 300m +-2 | Scenario: 10m distances Given a grid size of 10 meters diff --git a/features/testbot/weight.feature b/features/testbot/fastest.feature similarity index 84% rename from features/testbot/weight.feature rename to features/testbot/fastest.feature index 0e3551ff2..572280cd7 100644 --- a/features/testbot/weight.feature +++ b/features/testbot/fastest.feature @@ -1,5 +1,5 @@ -@routing @weight -Feature: Choosing route based on length, speed, etc +@routing @fastest +Feature: Choosing fastest route Background: Given the profile "testbot" @@ -22,7 +22,7 @@ Feature: Choosing route based on length, speed, etc | x | y | xa,atb,by | | y | x | by,atb,xa | - Scenario: Pick the shortest travel time, even when it's longer + Scenario: Pick the fastest route, even when it's longer Given the node map | | p | | | a | s | b | From 06c22a478f4a23ab808073dabbf66cb09a7f2536 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 12:39:12 +0100 Subject: [PATCH 027/161] fixing typo --- Descriptors/JSONDescriptor.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 140cde9fe..e1f93d1e9 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -262,23 +262,25 @@ public: std::vector shortestDifference(shortestSegments.size()); std::vector alternativeDifference(alternativeSegments.size()); std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) ); - if(0 < shortestDifference.size() ) { + int size_of_difference = shortestDifference.size(); + if(0 < size_of_difference ) { unsigned i = 0; - while( i < shortestDifference.size() && shortestDifference[i].nameID == shortestSegments[0].nameID) { + while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) { ++i; } - if(i < shortestDifference.size()) { + if(i < size_of_difference ) { shortestSegment2 = shortestDifference[i]; } } std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) ); - if(0 < alternativeDifference.size() ) { + size_of_difference = alternativeDifference.size(); + if(0 < size_of_difference ) { unsigned i = 0; - while( i < alternativeDifference.size() && alternativeDifference[i].nameID == alternativeSegments[0].nameID) { + while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) { ++i; } - if(i < alternativeDifference.size()) { + if(i < size_of_difference ) { alternativeSegment2 = alternativeDifference[i]; } } @@ -292,7 +294,7 @@ public: routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID); routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID); - routeNames.alternativePathName2 += sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID); + routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID); } } From e70adbb1cb022cc9d4df922e3f75f3e575ae45bd Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 12:59:36 +0100 Subject: [PATCH 028/161] Using const-refs instead of copies when iterating vectors --- DataStructures/NNGrid.h | 6 +++--- Descriptors/GPXDescriptor.h | 2 +- Descriptors/JSONDescriptor.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 9f280bc14..1ee131317 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -179,7 +179,7 @@ public: double dist = std::numeric_limits::max(); double r, tmpDist; - BOOST_FOREACH(_GridEdge candidate, candidates) { + BOOST_FOREACH(const _GridEdge & candidate, candidates) { if(candidate.belongsToTinyComponent && ignoreTinyComponents) continue; r = 0.; @@ -266,7 +266,7 @@ public: } _Coordinate tmp; double dist = (std::numeric_limits::max)(); - BOOST_FOREACH(_GridEdge candidate, candidates) { + BOOST_FOREACH(const _GridEdge & candidate, candidates) { double r = 0.; double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r); if(tmpDist < dist) { @@ -312,7 +312,7 @@ private: cellMap.insert(insertionVector.begin(), insertionVector.end()); } - inline bool DoubleEpsilonCompare(const double d1, const double d2) { + inline bool DoubleEpsilonCompare(const double d1, const double d2) const { return (std::fabs(d1 - d2) < FLT_EPSILON); } diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 2b9021ba5..17a3f9226 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -46,7 +46,7 @@ public: convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp); reply.content += "lon=\"" + tmp + "\">"; - BOOST_FOREACH(_PathData pathData, rawRoute.computedShortestPath) { + BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) { sEngine.GetCoordinatesForNodeID(pathData.node, current); convertInternalLatLonToString(current.lat, tmp); diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index e1f93d1e9..5cd24877b 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -246,7 +246,7 @@ public: reply.content += "}"; } - void GetRouteNames(std::vector & shortestSegments, std::vector & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) { + void GetRouteNames(std::vector & shortestSegments, std::vector & alternativeSegments, const SearchEngineT &sEngine, RouteNames & routeNames) { /*** extract names for both alternatives ***/ Segment shortestSegment1, shortestSegment2; From dbe1a4255c1359ad83ed15e344be1cfe75d31209 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 13:02:10 +0100 Subject: [PATCH 029/161] type change --- profile.lua | 210 +--------------------------------------------------- 1 file changed, 1 insertion(+), 209 deletions(-) mode change 100644 => 120000 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 100644 index c078647f6..000000000 --- a/profile.lua +++ /dev/null @@ -1,209 +0,0 @@ --- Begin of globals -require("lib/access") - -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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 } -access_tag_restricted = { ["destination"] = true, ["delivery"] = true } -access_tags = { "motorcar", "motor_vehicle", "vehicle" } -access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } -service_tag_restricted = { ["parking_aisle"] = true } -ignore_in_grid = { ["ferry"] = true } -restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } - -speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, --- ["track"] = 5, - ["ferry"] = 5, - ["default"] = 50 -} - -take_minimum_of_speeds = false -obey_oneway = true -obey_bollards = true -use_restrictions = true -ignore_areas = true -- future feature -traffic_signal_penalty = 2 -u_turn_penalty = 20 - --- End of globals - -function get_exceptions(vector) - for i,v in ipairs(restriction_exception_tags) do - vector:Add(v) - end -end - -local function parse_maxspeed(source) - if source == nil then - return 0 - end - local n = tonumber(source:match("%d*")) - if n == nil then - n = 0 - end - if string.match(source, "mph") or string.match(source, "mp/h") then - n = (n*1609)/1000; - end - return math.abs(n) -end - -function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; - end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end - end - return 1 -end - - -function way_function (way, numberOfNodesInWay) - - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name --- else --- way.name = highway -- if no name exists, use way type - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) - then - if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); - way.is_duration_set = true - end - way.direction = Way.bidirectional - if speed_profile[route] ~= nil then - highway = route; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) - end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end - - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end - - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel - - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 - return 1 -end - --- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT - -function node_vector_function(vector) - for v in vector.nodes do - node_function(v) - end -end diff --git a/profile.lua b/profile.lua new file mode 120000 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file From d6adc56b3a75fd0deae48981fd63afbcf072a73d Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 6 Jan 2013 15:44:15 +0100 Subject: [PATCH 030/161] add test for multiple except tag values in restrictions --- features/bicycle/restrictions.feature | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index 20ee13c44..6c5daf70b 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -249,3 +249,41 @@ Feature: Bike - Turn restrictions | from | to | route | | s | a | sj,aj | | s | b | sj,bj | + + @except + Scenario: Bike - Multiple except tag values + Given the node map + | s | j | a | + | | | b | + | | | c | + | | | d | + | | | e | + | | | f | + + And the ways + | nodes | oneway | + | sj | yes | + | ja | yes | + | jb | yes | + | jc | yes | + | jd | yes | + | je | yes | + | jf | yes | + + And the relations + | type | way:from | way:to | node:via | restriction | except | + | restriction | sj | ja | j | no_straight_on | | + | restriction | sj | jb | j | no_straight_on | bicycle | + | restriction | sj | jc | j | no_straight_on | bus; bicycle | + | restriction | sj | jd | j | no_straight_on | bicycle; motocar | + | restriction | sj | je | j | no_straight_on | bus, bicycle | + | restriction | sj | jf | j | no_straight_on | bicycle, bus | + + When I route I should get + | from | to | route | + | s | a | | + | s | b | sj,jb | + | s | c | sj,jc | + | s | d | sj,jd | + | s | e | | + | s | f | | From 5b3aacb4b2dd8dd77005319651c3dd009561a84a Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 17:48:18 +0100 Subject: [PATCH 031/161] removing stringstream --- Server/BasicDatastructures.h | 19 +++++---- Server/RequestHandler.h | 18 ++++---- Util/StringUtil.h | 79 ++++++++++++++---------------------- 3 files changed, 50 insertions(+), 66 deletions(-) diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h index c01d5d34a..cf3aa133f 100644 --- a/Server/BasicDatastructures.h +++ b/Server/BasicDatastructures.h @@ -21,8 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef BASIC_DATASTRUCTURES_H #define BASIC_DATASTRUCTURES_H #include +#include #include +#include "../Util/StringUtil.h" + namespace http { const std::string okString = "HTTP/1.0 200 OK\r\n"; @@ -70,15 +73,13 @@ struct Reply { std::vector HeaderstoBuffers(); std::string content; static Reply stockReply(status_type status); - void setSize(unsigned size) { - for (std::size_t i = 0; i < headers.size(); ++i) { - Header& h = headers[i]; - if("Content-Length" == h.name) { - std::stringstream sizeString; - sizeString << size; - h.value = sizeString.str(); - } - } + void setSize(const unsigned size) { + BOOST_FOREACH (const Header& h, headers) { + if("Content-Length" == h.name) { + std::string sizeString; + intToString(size,h.value ); + } + } } }; diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h index 35036a6ba..c801b7971 100644 --- a/Server/RequestHandler.h +++ b/Server/RequestHandler.h @@ -33,6 +33,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../DataStructures/HashTable.h" #include "../Plugins/BasePlugin.h" #include "../Plugins/RouteParameters.h" +#include "../Util/StringUtil.h" #include "../typedefs.h" namespace http { @@ -71,16 +72,17 @@ public: bool result = boost::spirit::qi::parse(it, request.end(), apiParser); // returns true if successful if (!result || (it != request.end()) ) { rep = http::Reply::stockReply(http::Reply::badRequest); - std::stringstream content; int position = std::distance(request.begin(), it); - content << "Input seems to be malformed close to position " << position << "
"; - content << "
";
-                content << req.uri << "
"; + std::string tmp_position_string; + intToString(position, tmp_position_string); + rep.content += "Input seems to be malformed close to position "; + rep.content += "
";
+                rep.content += request;
+                rep.content += tmp_position_string;
+                rep.content += "
"; for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i) - content << " "; - content << "^" << "
"; - content << "
"; - rep.content += content.str(); + rep.content += " "; + rep.content += "^
"; } else { //Finished parsing, lets call the right plugin to handle the request if(pluginMap.Holds(routeParameters.service)) { diff --git a/Util/StringUtil.h b/Util/StringUtil.h index 32e147c1f..0dc6df007 100644 --- a/Util/StringUtil.h +++ b/Util/StringUtil.h @@ -21,14 +21,14 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef STRINGUTIL_H_ #define STRINGUTIL_H_ -#include -#include #include -#include +#include #include #include +#include + #include "../DataStructures/Coordinate.h" #include "../typedefs.h" @@ -80,6 +80,20 @@ static inline int stringToInt(const std::string& input) { return value; } +static inline void doubleToString(const double value, std::string & output){ + output.clear(); + std::back_insert_iterator sink(output); + boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value); +} + +static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string & output){ + // The largest 32-bit integer is 4294967295, that is 10 chars + // On the safe side, add 1 for sign, and 1 for trailing zero + char buffer[12] ; + sprintf(buffer, "%g", value) ; + output = buffer ; +} + static inline void convertInternalLatLonToString(const int value, std::string & output) { char buffer[100]; buffer[10] = 0; // Nullterminierung @@ -106,70 +120,37 @@ static inline void convertInternalReversedCoordinateToString(const _Coordinate & output += " "; } -static inline void doubleToString(const double value, std::string & output){ - // The largest 32-bit integer is 4294967295, that is 10 chars - // On the safe side, add 1 for sign, and 1 for trailing zero - char buffer[12] ; - sprintf(buffer, "%f", value) ; - output = buffer ; -} - -static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string & output){ - // The largest 32-bit integer is 4294967295, that is 10 chars - // On the safe side, add 1 for sign, and 1 for trailing zero - char buffer[12] ; - sprintf(buffer, "%g", value) ; - output = buffer ; -} - -inline std::string & replaceAll(std::string &s, const std::string &sub, const std::string &other) { - assert(!sub.empty()); - size_t b = 0; - for (;;) { - b = s.find(sub, b); - if (b == s.npos) break; - s.replace(b, sub.size(), other); - b += other.size(); - } - return s; +inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) { + boost::replace_all(s, sub, other); } inline void stringSplit(const std::string &s, const char delim, std::vector& result) { - std::stringstream ss(s); - std::string item; - while(std::getline(ss, item, delim)) { - if(item.size() > 0) - result.push_back(item); - } + boost::split(result, s, boost::is_any_of(std::string(&delim))); } - static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"}; static std::string entities[] = {"&", """, "<", ">", "'", "&91;", "&93;", " \" }; -inline std::string HTMLEntitize( std::string result) { - for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); i++) { - result = replaceAll(result, originals[i], entities[i]); +inline std::string HTMLEntitize( std::string & result) { + for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) { + replaceAll(result, originals[i], entities[i]); } return result; } -inline std::string HTMLDeEntitize( std::string result) { - for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); i++) { - result = replaceAll(result, entities[i], originals[i]); +inline std::string HTMLDeEntitize( std::string & result) { + for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) { + replaceAll(result, entities[i], originals[i]); } return result; } -inline bool StringStartsWith(std::string & input, std::string & prefix) { - return (input.find(prefix) == 0); +inline bool StringStartsWith(const std::string & input, const std::string & prefix) { + return boost::starts_with(input, prefix); } - -/* - * Function returns a 'random' filename in temporary directors. - * May not be platform independent. - */ +// Function returns a 'random' filename in temporary directors. +// May not be platform independent. inline void GetTemporaryFileName(std::string & filename) { char buffer[L_tmpnam]; char * retPointer = tmpnam (buffer); From 864c2d9f497791ec0cb0374cdbb0b80163d33cff Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 17:58:02 +0100 Subject: [PATCH 032/161] stray const keyword removed that prevented build --- Server/BasicDatastructures.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h index cf3aa133f..e87656975 100644 --- a/Server/BasicDatastructures.h +++ b/Server/BasicDatastructures.h @@ -74,7 +74,7 @@ struct Reply { std::string content; static Reply stockReply(status_type status); void setSize(const unsigned size) { - BOOST_FOREACH (const Header& h, headers) { + BOOST_FOREACH ( Header& h, headers) { if("Content-Length" == h.name) { std::string sizeString; intToString(size,h.value ); From 2b5e11071969aa10639feb3aec2007a72c93519c Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 19:03:04 +0100 Subject: [PATCH 033/161] Splitting utility header with ambigious name into two files with better names --- DataStructures/MercatorUtil.h | 38 +++++++++++++++++++++++++ DataStructures/NNGrid.h | 4 +-- DataStructures/{Util.h => TimingUtil.h} | 26 ++--------------- Extractor/ExtractionContainers.h | 2 +- Extractor/ExtractorStructs.h | 2 +- Server/Connection.h | 1 - 6 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 DataStructures/MercatorUtil.h rename DataStructures/{Util.h => TimingUtil.h} (68%) diff --git a/DataStructures/MercatorUtil.h b/DataStructures/MercatorUtil.h new file mode 100644 index 000000000..15bea275a --- /dev/null +++ b/DataStructures/MercatorUtil.h @@ -0,0 +1,38 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +#ifndef MERCATORUTIL_H_ +#define MERCATORUTIL_H_ + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +inline double y2lat(double a) { + return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); +} + +inline double lat2y(double a) { + return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); +} + +#endif /* MERCATORUTIL_H_ */ diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 1ee131317..365f59675 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -44,12 +44,12 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include "DeallocatingVector.h" -//#include "ExtractorStructs.h" #include "GridEdge.h" #include "Percent.h" #include "PhantomNodes.h" -#include "Util.h" +#include "MercatorUtil.h" #include "StaticGraph.h" +#include "TimingUtil.h" #include "../Algorithms/Bresenham.h" namespace NNGrid{ diff --git a/DataStructures/Util.h b/DataStructures/TimingUtil.h similarity index 68% rename from DataStructures/Util.h rename to DataStructures/TimingUtil.h index 8448e4ce6..6e980e26f 100644 --- a/DataStructures/Util.h +++ b/DataStructures/TimingUtil.h @@ -18,16 +18,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ -#ifndef TIMEUTIL_H_ -#define TIMEUTIL_H_ +#ifndef TIMINGUTIL_H_ +#define TIMINGUTIL_H_ #include -#include #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif #ifdef _WIN32 #include @@ -43,13 +39,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #endif -#ifdef _WIN32 - #include -#else - #include -#endif -#include - /** Returns a timestamp (now) in seconds (incl. a fractional part). */ static inline double get_timestamp() { struct timeval tp; @@ -57,14 +46,5 @@ static inline double get_timestamp() { return double(tp.tv_sec) + tp.tv_usec / 1000000.; } -static inline double y2lat(double a) { return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); } -static inline double lat2y(double a) { return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); } -static inline unsigned boost_thread_id_hash(boost::thread::id const& id) { - std::stringstream ostr; - ostr << id; - std::tr1::hash h; - return h(ostr.str()); -} - -#endif /* TIMEUTIL_H_ */ +#endif /* TIMINGUTIL_H_ */ diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h index b683e7153..7e8a1d7be 100644 --- a/Extractor/ExtractionContainers.h +++ b/Extractor/ExtractionContainers.h @@ -25,7 +25,7 @@ #include #include "ExtractorStructs.h" -#include "../DataStructures/Util.h" +#include "../DataStructures/TimingUtil.h" class ExtractionContainers { public: diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index 36194f119..fe5dd1b40 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -34,7 +34,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../DataStructures/ImportNode.h" #include "../DataStructures/NodeCoords.h" #include "../DataStructures/Restriction.h" -#include "../DataStructures/Util.h" +#include "../DataStructures/TimingUtil.h" #include "../typedefs.h" typedef boost::unordered_map StringMap; diff --git a/Server/Connection.h b/Server/Connection.h index ea1ebd933..5dd4b7913 100644 --- a/Server/Connection.h +++ b/Server/Connection.h @@ -30,7 +30,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include -#include "../DataStructures/Util.h" #include "BasicDatastructures.h" #include "RequestHandler.h" #include "RequestParser.h" From fd79e81fe5dae879e88ff6dd2bd7e906b57a312d Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 19:06:17 +0100 Subject: [PATCH 034/161] Removing explicit namespace usage --- createHierarchy.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 2596d312b..886078a42 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -49,8 +49,6 @@ extern "C" { #include "Util/LuaUtil.h" #include "Util/StringUtil.h" -using namespace std; - typedef QueryEdge::EdgeData EdgeData; typedef DynamicGraph::InputEdge InputEdge; typedef StaticGraph::InputEdge StaticEdge; @@ -77,7 +75,7 @@ int main (int argc, char *argv[]) { omp_set_num_threads(numberOfThreads); INFO("Using restrictions from file: " << argv[2]); - std::ifstream restrictionsInstream(argv[2], ios::binary); + std::ifstream restrictionsInstream(argv[2], std::ios::binary); if(!restrictionsInstream.good()) { ERR("Could not access files"); } @@ -214,11 +212,11 @@ int main (int argc, char *argv[]) { */ INFO("Building Node Array"); - sort(contractedEdgeList.begin(), contractedEdgeList.end()); + std::sort(contractedEdgeList.begin(), contractedEdgeList.end()); unsigned numberOfNodes = 0; unsigned numberOfEdges = contractedEdgeList.size(); INFO("Serializing compacted graph"); - ofstream edgeOutFile(graphOut, ios::binary); + std::ofstream edgeOutFile(graphOut, std::ios::binary); BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) { if(edge.source > numberOfNodes) { From 2af9fcad68a27cb1f02e7521b72deca91c8912c1 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 6 Jan 2013 19:38:03 +0100 Subject: [PATCH 035/161] Saving 3 bytes per original edge. --- DataStructures/NodeInformationHelpDesk.h | 35 ++++++++++++++++-------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/DataStructures/NodeInformationHelpDesk.h b/DataStructures/NodeInformationHelpDesk.h index abf05b71a..1733cfaba 100644 --- a/DataStructures/NodeInformationHelpDesk.h +++ b/DataStructures/NodeInformationHelpDesk.h @@ -25,13 +25,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include +#include + #include "../typedefs.h" #include "../DataStructures/QueryEdge.h" #include "NNGrid.h" #include "PhantomNodes.h" #include "NodeCoords.h" -class NodeInformationHelpDesk{ +class NodeInformationHelpDesk : boost::noncopyable{ public: NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) { readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput); @@ -59,34 +61,43 @@ public: DEBUG("Loading edge data"); unsigned numberOfOrigEdges(0); edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned)); - origEdgeData.resize(numberOfOrigEdges); - edgesInStream.read((char*)&(origEdgeData[0]), numberOfOrigEdges*sizeof(OriginalEdgeData)); + origEdgeData_viaNode.resize(numberOfOrigEdges); + origEdgeData_nameID.resize(numberOfOrigEdges); + origEdgeData_turnInstruction.resize(numberOfOrigEdges); + + OriginalEdgeData deserialized_originalEdgeData; + for(unsigned i = 0; i < numberOfOrigEdges; ++i) { + edgesInStream.read((char*)&(deserialized_originalEdgeData), sizeof(OriginalEdgeData)); + origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode; + origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID; + origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction; + } edgesInStream.close(); DEBUG("Loaded " << numberOfOrigEdges << " orig edges"); DEBUG("Opening NN indices"); readOnlyGrid->OpenIndexFiles(); } - void initNNGrid() { - readOnlyGrid->OpenIndexFiles(); - } +// void initNNGrid() { +// readOnlyGrid->OpenIndexFiles(); +// } inline int getLatitudeOfNode(const unsigned id) const { - const NodeID node = origEdgeData.at(id).viaNode; + const NodeID node = origEdgeData_viaNode.at(id); return coordinateVector.at(node).lat; } inline int getLongitudeOfNode(const unsigned id) const { - const NodeID node = origEdgeData.at(id).viaNode; + const NodeID node = origEdgeData_viaNode.at(id); return coordinateVector.at(node).lon; } inline unsigned getNameIndexFromEdgeID(const unsigned id) const { - return origEdgeData.at(id).nameID; + return origEdgeData_nameID.at(id); } inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const { - return origEdgeData.at(id).turnInstruction; + return origEdgeData_turnInstruction.at(id); } inline NodeID getNumberOfNodes() const { return numberOfNodes; } @@ -114,7 +125,9 @@ public: private: std::vector<_Coordinate> coordinateVector; - std::vector origEdgeData; + std::vector origEdgeData_viaNode; + std::vector origEdgeData_nameID; + std::vector origEdgeData_turnInstruction; ReadOnlyGrid * readOnlyGrid; const unsigned numberOfNodes; From 54774726b2c353c09efcfa78d5fa04828fd125aa Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 10 Jan 2013 11:58:39 +0100 Subject: [PATCH 036/161] test separate weight/speed, still marked as @todo --- features/testbot/impedance.feature | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 features/testbot/impedance.feature diff --git a/features/testbot/impedance.feature b/features/testbot/impedance.feature new file mode 100644 index 000000000..0e5362309 --- /dev/null +++ b/features/testbot/impedance.feature @@ -0,0 +1,96 @@ +@routing @testbot @impedance @todo +Feature: Setting impedance and speed separately +These tests assume that the speed is not factored into the impedance by OSRM internally. +Instead the speed can optionally be factored into the weiht in the lua profile. + +Note: With the default grid size of 100m, the diagonals has a length if 141.42m + + Background: + Given the profile "testbot" + + Scenario: Use impedance to pick route, even when longer/slower + Given the node map + | | s | | t | | u | | v | | + | a | | b | | c | | d | | e | + + And the ways + | nodes | impedance | + | ab | 1.3 | + | asb | 1 | + | bc | 1.5 | + | btc | 1 | + | cd | 0.015 | + | cud | 0.010 | + | de | 150000 | + | dve | 100000 | + + When I route I should get + | from | to | route | distance | + | a | b | ab | 200m +-1 | + | b | a | ab | 200m +-1 | + | b | c | btc | 282m +-1 | + | c | b | btc | 282m +-1 | + | c | d | cud | 282m +-1 | + | d | c | cud | 282m +-1 | + | d | e | dve | 282m +-1 | + | e | d | dve | 282m +-1 | + + Scenario: Weight should default to 1 + Given the node map + | | s | | t | | + | a | | b | | c | + + And the ways + | nodes | impedance | + | ab | 1.40 | + | asb | | + | bc | 1.42 | + | btc | | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ab | + | b | c | btc | + | c | b | btc | + + Scenario: Use both impedance and speed (multiplied) when picking route + OSRM should not factor speed into impedance internally. However, the profile can choose to do so, + and this test expect the testbot profile to do it. + Given the node map + | | s | | t | | + | a | | b | | c | + + And the ways + | nodes | impedance | highway | + | ab | 2.80 | primary | + | asb | 1 | secondary | + | bc | 2.84 | primary | + | btc | 1 | secondary | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ab | + | b | c | btc | + | c | b | btc | + + Scenario: Weight should influence neither speed nor travel time. + Given the node map + | a | b | c | + | t | | | + + And the ways + | nodes | + | ab | + | bc | + | at | + + When I route I should get + | from | to | route | distance | time | + | a | b | ab | 100m +-1 | 10s +-1 | + | b | a | ab | 100m +-1 | 10s +-1 | + | b | c | bc | 100m +-1 | 10s +-1 | + | c | b | bc | 100m +-1 | 10s +-1 | + | a | c | ab,bc | 200m +-1 | 20s +-1 | + | c | a | bc,ab | 200m +-1 | 20s +-1 | From 2e3947cc6d93aff957afef7d05df1ed711334125 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 10 Jan 2013 17:05:41 +0100 Subject: [PATCH 037/161] support list of ways in relations tests --- features/step_definitions/data.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb index fc34105fb..c2cf35c3b 100644 --- a/features/step_definitions/data.rb +++ b/features/step_definitions/data.rb @@ -90,14 +90,18 @@ Given /^the relations$/ do |table| relation = OSM::Relation.new make_osm_id, OSM_USER, OSM_TIMESTAMP row.each_pair do |key,value| if key =~ /^node:(.*)/ - raise "***invalid relation node member '#{value}', must be single character" unless value.size == 1 - node = find_node_by_name(value) - raise "*** unknown relation node member '#{value}'" unless node - relation << OSM::Member.new( 'node', node.id, $1 ) + value.split(',').map { |v| v.strip }.each do |node_name| + raise "***invalid relation node member '#{node_name}', must be single character" unless node_name.size == 1 + node = find_node_by_name(node_name) + raise "*** unknown relation node member '#{node_name}'" unless node + relation << OSM::Member.new( 'node', node.id, $1 ) + end elsif key =~ /^way:(.*)/ - way = find_way_by_name(value) - raise "*** unknown relation way member '#{value}'" unless way - relation << OSM::Member.new( 'way', way.id, $1 ) + value.split(',').map { |v| v.strip }.each do |way_name| + way = find_way_by_name(way_name) + raise "*** unknown relation way member '#{way_name}'" unless way + relation << OSM::Member.new( 'way', way.id, $1 ) + end elsif key =~ /^(.*):(.*)/ raise "*** unknown relation member type '#{$1}', must be either 'node' or 'way'" else From 7d7baa70a95123da8034f22972e6f911d1369d3c Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 10 Jan 2013 17:06:16 +0100 Subject: [PATCH 038/161] test routes parsing (@todo) --- features/testbot/routes.feature | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 features/testbot/routes.feature diff --git a/features/testbot/routes.feature b/features/testbot/routes.feature new file mode 100644 index 000000000..763b34793 --- /dev/null +++ b/features/testbot/routes.feature @@ -0,0 +1,35 @@ +@routing @testbot @routes @todo +Feature: OSM Route Relation + + Background: + Given the profile "testbot" + + Scenario: Prioritize ways that are part of route relations + This scenario assumes that the testbot uses an impedance of 0.5 for ways that are part of 'testbot' routes. + + Given the node map + | s | | | t | | | | + | a | | | b | | | c | + | | | | | | | | + | | | | u | | | v | + + And the ways + | nodes | + | ab | + | bc | + | as | + | stb | + | bu | + | uvc | + + And the relations + | type | route | way:route | + | route | testbot | as,stb | + | route | testbot | bu,uvc | + + When I route I should get + | from | to | route | distance | time | + | b | c | bc | 300m +-1 | 30s +-1 | + | c | b | bc | 300m +-1 | 30s +-1 | + | a | b | as,stb | 500m +-1 | 50s +-1 | + | b | a | stb,as | 500m +-1 | 50s +-1 | \ No newline at end of file From 8158e7f1c53d92ae2ac318870ccd084ea95b4e30 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 18:16:08 +0100 Subject: [PATCH 039/161] Using explicit 64bit integer instead of compiler-dependent long long --- Extractor/PBFParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 42a2571da..d86fbc457 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -281,7 +281,7 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { if(isRestriction) { - long long lastRef = 0; + int64_t lastRef = 0; _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); From 724e96f0c1c683b12cc280dc98d7e3033558ef93 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 11 Jan 2013 18:14:43 +0100 Subject: [PATCH 040/161] test different forw/backw settings (@todo) --- features/testbot/opposite.feature | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 features/testbot/opposite.feature diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature new file mode 100644 index 000000000..176974965 --- /dev/null +++ b/features/testbot/opposite.feature @@ -0,0 +1,19 @@ +@routing @opposite @todo +Feature: Separate settings for forward/backward direction + + Background: + Given the profile "testbot" + + @smallest + Scenario: Going against the flow + Given the node map + | a | b | + + And the ways + | nodes | highway | + | ab | river | + + When I route I should get + | from | to | route | distance | time | + | a | b | ab | 100m | 10s | + | b | a | ab | 100m | 20s | From 7449f81ed4214ee5d48c661c0d44cc30849352a3 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 18:36:00 +0100 Subject: [PATCH 041/161] Reordering members in struct to actually exploit four byte padding, partially fixes #563 --- DataStructures/QueryEdge.h | 2 +- profile.lua | 210 ++++++++++++++++++++++++++++++++++++- 2 files changed, 210 insertions(+), 2 deletions(-) mode change 120000 => 100644 profile.lua diff --git a/DataStructures/QueryEdge.h b/DataStructures/QueryEdge.h index 72cbf0f07..3a2aecb82 100644 --- a/DataStructures/QueryEdge.h +++ b/DataStructures/QueryEdge.h @@ -41,8 +41,8 @@ struct QueryEdge { NodeID target; struct EdgeData { NodeID id:31; - int distance:30; bool shortcut:1; + int distance:30; bool forward:1; bool backward:1; } data; diff --git a/profile.lua b/profile.lua deleted file mode 120000 index bad7e6bb5..000000000 --- a/profile.lua +++ /dev/null @@ -1 +0,0 @@ -profiles/car.lua \ No newline at end of file diff --git a/profile.lua b/profile.lua new file mode 100644 index 000000000..c078647f6 --- /dev/null +++ b/profile.lua @@ -0,0 +1,209 @@ +-- Begin of globals +require("lib/access") + +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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 } +access_tag_restricted = { ["destination"] = true, ["delivery"] = true } +access_tags = { "motorcar", "motor_vehicle", "vehicle" } +access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } +service_tag_restricted = { ["parking_aisle"] = true } +ignore_in_grid = { ["ferry"] = true } +restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } + +speed_profile = { + ["motorway"] = 90, + ["motorway_link"] = 75, + ["trunk"] = 85, + ["trunk_link"] = 70, + ["primary"] = 65, + ["primary_link"] = 60, + ["secondary"] = 55, + ["secondary_link"] = 50, + ["tertiary"] = 40, + ["tertiary_link"] = 30, + ["unclassified"] = 25, + ["residential"] = 25, + ["living_street"] = 10, + ["service"] = 15, +-- ["track"] = 5, + ["ferry"] = 5, + ["default"] = 50 +} + +take_minimum_of_speeds = false +obey_oneway = true +obey_bollards = true +use_restrictions = true +ignore_areas = true -- future feature +traffic_signal_penalty = 2 +u_turn_penalty = 20 + +-- End of globals + +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end + +local function parse_maxspeed(source) + if source == nil then + return 0 + end + local n = tonumber(source:match("%d*")) + if n == nil then + n = 0 + end + if string.match(source, "mph") or string.match(source, "mp/h") then + n = (n*1609)/1000; + end + return math.abs(n) +end + +function node_function (node) + local barrier = node.tags:Find ("barrier") + local access = Access.find_access_tag(node, access_tags_hierachy) + local traffic_signal = node.tags:Find("highway") + + --flag node if it carries a traffic light + + if traffic_signal == "traffic_signals" then + node.traffic_light = true; + end + + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + return + else + node.bollard = true + end + end + return 1 +end + + +function way_function (way, numberOfNodesInWay) + + -- A way must have two nodes or more + if(numberOfNodesInWay < 2) then + return 0; + end + + -- First, get the properties of each way that we come across + local highway = way.tags:Find("highway") + local name = way.tags:Find("name") + local ref = way.tags:Find("ref") + local junction = way.tags:Find("junction") + local route = way.tags:Find("route") + local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local barrier = way.tags:Find("barrier") + local oneway = way.tags:Find("oneway") + local cycleway = way.tags:Find("cycleway") + local duration = way.tags:Find("duration") + local service = way.tags:Find("service") + local area = way.tags:Find("area") + local access = Access.find_access_tag(way, access_tags_hierachy) + + -- Second, parse the way according to these properties + + if ignore_areas and ("yes" == area) then + return 0 + end + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] then + return 0 + end + + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name +-- else +-- way.name = highway -- if no name exists, use way type + end + + if "roundabout" == junction then + way.roundabout = true; + end + + -- Handling ferries and piers + if (speed_profile[route] ~= nil and speed_profile[route] > 0) + then + if durationIsValid(duration) then + way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); + way.is_duration_set = true + end + way.direction = Way.bidirectional + if speed_profile[route] ~= nil then + highway = route; + end + if not way.is_duration_set then + way.speed = speed_profile[highway] + end + end + + -- Set the avg speed on the way if it is accessible by road class + if (speed_profile[highway] ~= nil and way.speed == -1 ) then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile[highway], maxspeed) + end + + -- Set the avg speed on ways that are marked accessible + if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile["default"], maxspeed) + end + + -- Set access restriction flag if access is allowed under certain restrictions only + if access ~= "" and access_tag_restricted[access] then + way.is_access_restricted = true + end + + -- Set access restriction flag if service is allowed under certain restrictions only + if service ~= "" and service_tag_restricted[service] then + way.is_access_restricted = true + end + + -- Set direction according to tags on way + if obey_oneway then + if oneway == "no" or oneway == "0" or oneway == "false" then + way.direction = Way.bidirectional + elseif oneway == "-1" then + way.direction = Way.opposite + elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then + way.direction = Way.oneway + else + way.direction = Way.bidirectional + end + else + way.direction = Way.bidirectional + end + + -- Override general direction settings of there is a specific one for our mode of travel + + if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then + way.ignore_in_grid = true + end + way.type = 1 + return 1 +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 From f7d79209dc14249a59d0f194574066cab80a55c1 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 20:20:22 +0100 Subject: [PATCH 042/161] Fixing dereference after null check (Coverity: CID 967038) --- Extractor/XMLParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 47506b736..6449add3f 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -168,9 +168,9 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { if(0 == std::string((const char *) value).find("only_")) restriction.restriction.flags.isOnly = true; } - } - if ( xmlStrEqual(k, (const xmlChar *) "except") ) { - exception_of_restriction_tag = (const char*) value; + if ( xmlStrEqual(k, (const xmlChar *) "except") ) { + exception_of_restriction_tag = (const char*) value; + } } if ( k != NULL ) From 845c73af738ef64a9b3879fb7e4006f1a56d10c6 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 20:44:35 +0100 Subject: [PATCH 043/161] Removing unused table, Uninitialized scalar field (UNINIT_CTOR), Coverity CID 751302 --- Algorithms/CRC32.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Algorithms/CRC32.h b/Algorithms/CRC32.h index d84a56808..6321030b7 100644 --- a/Algorithms/CRC32.h +++ b/Algorithms/CRC32.h @@ -27,7 +27,6 @@ class CRC32 { private: unsigned crc; - unsigned slowcrc_table[1<<8]; typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type; typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc); From 2ccd3da5b3e84fe6e961e0bc4c5188ee4a12bb78 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 22:13:02 +0100 Subject: [PATCH 044/161] replacing unsafe strcpy operations --- DataStructures/NNGrid.h | 6 ++++-- Util/GraphLoader.h | 8 ++++---- createHierarchy.cpp | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 365f59675..ca13f0d7c 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -95,7 +95,7 @@ public: #ifndef ROUTED template - inline void ConstructGrid(DeallocatingVector & edgeList, char * ramIndexOut, char * fileIndexOut) { + inline void ConstructGrid(DeallocatingVector & edgeList, const char * ramIndexOut, const char * fileIndexOut) { //TODO: Implement this using STXXL-Streams Percent p(edgeList.size()); BOOST_FOREACH(EdgeT & edge, edgeList) { @@ -316,6 +316,7 @@ private: return (std::fabs(d1 - d2) < FLT_EPSILON); } +#ifndef ROUTED inline unsigned FillCell(std::vector& entriesWithSameRAMIndex, const uint64_t fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) { std::vector tmpBuffer(32*32*4096,0); uint64_t indexIntoTmpBuffer = 0; @@ -393,6 +394,7 @@ private: vectorWithSameFileIndex.clear(); return counter; } +#endif inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const { unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex); @@ -578,9 +580,9 @@ private: const static uint64_t END_OF_BUCKET_DELIMITER = boost::integer_traits::const_max; - std::ofstream indexOutFile; std::ifstream ramInFile; #ifndef ROUTED + std::ofstream indexOutFile; stxxl::vector entries; #endif std::vector ramIndexTable; //8 MB for first level index in RAM diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index ef04f8d8f..b22086c39 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -169,14 +169,14 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL edgeList[i]._source = UINT_MAX; } else { //edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction - edgeList[i-1].forward = ~edgeList[i].isForward(); - edgeList[i-1].backward = ~edgeList[i].isBackward(); + edgeList[i-1].forward = !edgeList[i].isForward(); + edgeList[i-1].backward = !edgeList[i].isBackward(); } } else if (edgeFlagsAreSuperSet2) { if(edgeList[i-1].weight() <= edgeList[i].weight()) { //edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction - edgeList[i].forward = ~edgeList[i-1].isForward(); - edgeList[i].backward = ~edgeList[i-1].isBackward(); + edgeList[i].forward = !edgeList[i-1].isForward(); + edgeList[i].backward = !edgeList[i-1].isBackward(); } else { //edge i is smaller and goes in both direction. Throw away edge i-1 edgeList[i-1]._source = UINT_MAX; diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 886078a42..a638fcd18 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -92,12 +92,12 @@ int main (int argc, char *argv[]) { ERR("Cannot open " << argv[1]); } - char nodeOut[1024]; strcpy(nodeOut, argv[1]); strcat(nodeOut, ".nodes"); - char edgeOut[1024]; strcpy(edgeOut, argv[1]); strcat(edgeOut, ".edges"); - char graphOut[1024]; strcpy(graphOut, argv[1]); strcat(graphOut, ".hsgr"); - char ramIndexOut[1024]; strcpy(ramIndexOut, argv[1]); strcat(ramIndexOut, ".ramIndex"); - char fileIndexOut[1024]; strcpy(fileIndexOut, argv[1]); strcat(fileIndexOut, ".fileIndex"); - char levelInfoOut[1024]; strcpy(levelInfoOut, argv[1]); strcat(levelInfoOut, ".levels"); + std::string nodeOut(argv[1]); nodeOut += ".nodes"; + std::string edgeOut(argv[1]); edgeOut += ".edges"; + std::string graphOut(argv[1]); graphOut += ".hsgr"; + std::string ramIndexOut(argv[1]); ramIndexOut += ".ramIndex"; + std::string fileIndexOut(argv[1]); fileIndexOut += ".fileIndex"; + std::string levelInfoOut(argv[1]); levelInfoOut += ".levels"; /*** Setup Scripting Environment ***/ if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) { @@ -150,7 +150,7 @@ int main (int argc, char *argv[]) { INFO("Generating edge-expanded graph representation"); EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); std::vector().swap(edgeList); - edgeBasedGraphFactory->Run(edgeOut); + edgeBasedGraphFactory->Run(edgeOut.c_str()); std::vector<_Restriction>().swap(inputRestrictions); std::vector().swap(bollardNodes); std::vector().swap(trafficLightNodes); @@ -163,7 +163,7 @@ int main (int argc, char *argv[]) { */ INFO("writing node map ..."); - std::ofstream mapOutFile(nodeOut, std::ios::binary); + std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary); mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo)); mapOutFile.close(); std::vector().swap(internalToExternalNodeMapping); @@ -186,7 +186,7 @@ int main (int argc, char *argv[]) { INFO("building grid ..."); WritableGrid * writeableGrid = new WritableGrid(); - writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut, fileIndexOut); + writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut.c_str(), fileIndexOut.c_str()); delete writeableGrid; IteratorbasedCRC32 > crc32; unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); @@ -216,7 +216,7 @@ int main (int argc, char *argv[]) { unsigned numberOfNodes = 0; unsigned numberOfEdges = contractedEdgeList.size(); INFO("Serializing compacted graph"); - std::ofstream edgeOutFile(graphOut, std::ios::binary); + std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary); BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) { if(edge.source > numberOfNodes) { From a64420d700b621d58663f4070c7d488e94275d25 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 11 Jan 2013 22:22:57 +0100 Subject: [PATCH 045/161] further const'ing --- DataStructures/NNGrid.h | 2 +- DataStructures/NodeInformationHelpDesk.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index ca13f0d7c..92a6594e6 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -547,7 +547,7 @@ private: } } - inline unsigned GetFileIndexForLatLon(const int lt, const int ln) { + inline unsigned GetFileIndexForLatLon(const int lt, const int ln) const { double lat = lt/100000.; double lon = ln/100000.; diff --git a/DataStructures/NodeInformationHelpDesk.h b/DataStructures/NodeInformationHelpDesk.h index 1733cfaba..029d30def 100644 --- a/DataStructures/NodeInformationHelpDesk.h +++ b/DataStructures/NodeInformationHelpDesk.h @@ -107,7 +107,7 @@ public: return readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result); } - inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) const { + inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) { return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode, zoomLevel); } From 7f69857376fd9b3a7c2eb9d267d57c03bace1410 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:40:12 +0100 Subject: [PATCH 046/161] Support for backward speed in extractor --- Extractor/ExtractorCallbacks.cpp | 99 +++++++++++++++++++----------- Extractor/ExtractorStructs.h | 14 +++-- Extractor/ScriptingEnvironment.cpp | 1 + 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 3db1d8d8b..75da55032 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -44,8 +44,8 @@ or see http://www.gnu.org/licenses/agpl.txt. ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; } ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) { - externalMemory = ext; - stringMap = strMap; + externalMemory = ext; + stringMap = strMap; } ExtractorCallbacks::~ExtractorCallbacks() { @@ -64,42 +64,71 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &w) { - /*** Store name of way and split it into edge segments ***/ +bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { + if ( parsed_way.speed > 0 ) { //Only true if the way is specified by the speed profile + if(parsed_way.id == UINT_MAX){ + WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); + return true; + } + //Get the unique identifier for the street name + const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); + if(string_map_iterator == stringMap->end()) { + parsed_way.nameID = externalMemory->nameVector.size(); + externalMemory->nameVector.push_back(parsed_way.name); + stringMap->insert(StringMap::value_type(parsed_way.name, parsed_way.nameID)); + } else { + parsed_way.nameID = string_map_iterator->second; + } - if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile + if ( parsed_way.direction == _Way::opposite ){ + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + } - //Get the unique identifier for the street name - const StringMap::const_iterator strit = stringMap->find(w.name); - if(strit == stringMap->end()) { - w.nameID = externalMemory->nameVector.size(); - externalMemory->nameVector.push_back(w.name); - stringMap->insert(StringMap::value_type(w.name, w.nameID)); - } else { - w.nameID = strit->second; - } + if( parsed_way.backward_speed > 0 && parsed_way.direction == _Way::bidirectional) { + parsed_way.direction == _Way::oneway; + } - if(fabs(-1. - w.speed) < FLT_EPSILON){ - WARN("found way with bogus speed, id: " << w.id); - return true; - } - if(w.id == UINT_MAX) { - WARN("found way with unknown type: " << w.id); - return true; - } + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + (_Way::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? _Way::oneway : parsed_way.direction), + parsed_way.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted + ) + ); + externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); + } + externalMemory->usedNodeIDs.push_back(parsed_way.path.back()); - if ( w.direction == _Way::opposite ){ - std::reverse( w.path.begin(), w.path.end() ); - } + //The following information is needed to identify start and end segments of restrictions + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); - for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted)); - externalMemory->usedNodeIDs.push_back(w.path[n]); - } - externalMemory->usedNodeIDs.push_back(w.path.back()); - - //The following information is needed to identify start and end segments of restrictions - externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1])); - } - return true; + if ( parsed_way.backward_speed > 0 ) { //Only true if the way should be split + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + _Way::oneway, + parsed_way.backward_speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted, + (_Way::oneway == parsed_way.direction) + ) + ); + } + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); + } + } + return true; } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe5dd1b40..ad508fdaf 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -52,6 +52,7 @@ struct _Way { keyVals.EraseAll(); direction = _Way::notSure; speed = -1; + backward_speed = -1; type = -1; access = true; roundabout = false; @@ -67,6 +68,7 @@ struct _Way { unsigned nameID; std::string name; double speed; + double backward_speed; short type; bool access; bool roundabout; @@ -86,10 +88,13 @@ struct _Relation { }; struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) { + _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { + assert(0 <= type); + } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -102,6 +107,7 @@ struct _Edge { bool ignoreInGrid; bool isDurationSet; bool isAccessRestricted; + bool isContraFlow; _Coordinate startCoord; _Coordinate targetCoord; diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index c2f42d79d..b4b6af54e 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -68,6 +68,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::class_<_Way>("Way") .def(luabind::constructor<>()) .def_readwrite("name", &_Way::name) + .def_readwrite("backward_speed", &_Way::backward_speed) .def_readwrite("speed", &_Way::speed) .def_readwrite("type", &_Way::type) .def_readwrite("access", &_Way::access) From b19e2fbafedd4600b60bfa4bce7364899b94d2b0 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:42:04 +0100 Subject: [PATCH 047/161] Fixing test for opposite directions --- features/testbot/opposite.feature | 12 ++++++------ profiles/testbot.lua | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 176974965..9b5df779d 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,4 +1,4 @@ -@routing @opposite @todo +@routing @opposite Feature: Separate settings for forward/backward direction Background: @@ -7,13 +7,13 @@ Feature: Separate settings for forward/backward direction @smallest Scenario: Going against the flow Given the node map - | a | b | + | a | b | c | d | And the ways | nodes | highway | - | ab | river | + | abcd | river | When I route I should get - | from | to | route | distance | time | - | a | b | ab | 100m | 10s | - | b | a | ab | 100m | 20s | + | from | to | route | distance | time | + | a | d | abcd | 300 +- 1m | 30s | + | d | a | abcd | 300 +- 1m | 55s | diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 3eb1ff339..341cb6d23 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -56,6 +56,12 @@ function way_function (way, numberOfNodesInWay) way.speed = speed_profile[highway] or speed_profile['default'] end + if(highway == "river") then + local temp_speed = way.speed; + way.speed = temp_speed*3/2 + way.backward_speed = temp_speed*2/3 + end + if oneway == "no" or oneway == "0" or oneway == "false" then way.direction = Way.bidirectional elseif oneway == "-1" then From 9da4e18099fae716e55c6345fca9c23bfc4f37dc Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 18:59:38 +0100 Subject: [PATCH 048/161] Reordering padded struct --- Contractor/EdgeBasedGraphFactory.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 62a119e81..2b4c18d7f 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -53,14 +53,14 @@ private: struct _NodeBasedEdgeData { int distance; unsigned edgeBasedNodeID; - unsigned nameID:31; + unsigned nameID; + short type; + bool isAccessRestricted; bool shortcut:1; bool forward:1; bool backward:1; bool roundabout:1; bool ignoreInGrid:1; - short type; - bool isAccessRestricted; }; struct _EdgeBasedEdgeData { From 1a6c01769ea990babcdde1e7a29cc9036d06f820 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:40:12 +0100 Subject: [PATCH 049/161] Support for backward speed in extractor --- Extractor/ExtractorCallbacks.cpp | 99 +++++++++++++++++++----------- Extractor/ExtractorStructs.h | 14 +++-- Extractor/ScriptingEnvironment.cpp | 1 + 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 3db1d8d8b..75da55032 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -44,8 +44,8 @@ or see http://www.gnu.org/licenses/agpl.txt. ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; } ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) { - externalMemory = ext; - stringMap = strMap; + externalMemory = ext; + stringMap = strMap; } ExtractorCallbacks::~ExtractorCallbacks() { @@ -64,42 +64,71 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &w) { - /*** Store name of way and split it into edge segments ***/ +bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { + if ( parsed_way.speed > 0 ) { //Only true if the way is specified by the speed profile + if(parsed_way.id == UINT_MAX){ + WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); + return true; + } + //Get the unique identifier for the street name + const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); + if(string_map_iterator == stringMap->end()) { + parsed_way.nameID = externalMemory->nameVector.size(); + externalMemory->nameVector.push_back(parsed_way.name); + stringMap->insert(StringMap::value_type(parsed_way.name, parsed_way.nameID)); + } else { + parsed_way.nameID = string_map_iterator->second; + } - if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile + if ( parsed_way.direction == _Way::opposite ){ + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + } - //Get the unique identifier for the street name - const StringMap::const_iterator strit = stringMap->find(w.name); - if(strit == stringMap->end()) { - w.nameID = externalMemory->nameVector.size(); - externalMemory->nameVector.push_back(w.name); - stringMap->insert(StringMap::value_type(w.name, w.nameID)); - } else { - w.nameID = strit->second; - } + if( parsed_way.backward_speed > 0 && parsed_way.direction == _Way::bidirectional) { + parsed_way.direction == _Way::oneway; + } - if(fabs(-1. - w.speed) < FLT_EPSILON){ - WARN("found way with bogus speed, id: " << w.id); - return true; - } - if(w.id == UINT_MAX) { - WARN("found way with unknown type: " << w.id); - return true; - } + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + (_Way::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? _Way::oneway : parsed_way.direction), + parsed_way.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted + ) + ); + externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); + } + externalMemory->usedNodeIDs.push_back(parsed_way.path.back()); - if ( w.direction == _Way::opposite ){ - std::reverse( w.path.begin(), w.path.end() ); - } + //The following information is needed to identify start and end segments of restrictions + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); - for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted)); - externalMemory->usedNodeIDs.push_back(w.path[n]); - } - externalMemory->usedNodeIDs.push_back(w.path.back()); - - //The following information is needed to identify start and end segments of restrictions - externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1])); - } - return true; + if ( parsed_way.backward_speed > 0 ) { //Only true if the way should be split + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + _Way::oneway, + parsed_way.backward_speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted, + (_Way::oneway == parsed_way.direction) + ) + ); + } + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); + } + } + return true; } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe5dd1b40..ad508fdaf 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -52,6 +52,7 @@ struct _Way { keyVals.EraseAll(); direction = _Way::notSure; speed = -1; + backward_speed = -1; type = -1; access = true; roundabout = false; @@ -67,6 +68,7 @@ struct _Way { unsigned nameID; std::string name; double speed; + double backward_speed; short type; bool access; bool roundabout; @@ -86,10 +88,13 @@ struct _Relation { }; struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) { + _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { + assert(0 <= type); + } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -102,6 +107,7 @@ struct _Edge { bool ignoreInGrid; bool isDurationSet; bool isAccessRestricted; + bool isContraFlow; _Coordinate startCoord; _Coordinate targetCoord; diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index c2f42d79d..b4b6af54e 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -68,6 +68,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::class_<_Way>("Way") .def(luabind::constructor<>()) .def_readwrite("name", &_Way::name) + .def_readwrite("backward_speed", &_Way::backward_speed) .def_readwrite("speed", &_Way::speed) .def_readwrite("type", &_Way::type) .def_readwrite("access", &_Way::access) From 7f311551ddfa8a5cc8fc21c13c1d5dcbed1775f9 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:42:04 +0100 Subject: [PATCH 050/161] Fixing test for opposite directions --- features/testbot/opposite.feature | 12 ++++++------ profiles/testbot.lua | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 176974965..9b5df779d 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,4 +1,4 @@ -@routing @opposite @todo +@routing @opposite Feature: Separate settings for forward/backward direction Background: @@ -7,13 +7,13 @@ Feature: Separate settings for forward/backward direction @smallest Scenario: Going against the flow Given the node map - | a | b | + | a | b | c | d | And the ways | nodes | highway | - | ab | river | + | abcd | river | When I route I should get - | from | to | route | distance | time | - | a | b | ab | 100m | 10s | - | b | a | ab | 100m | 20s | + | from | to | route | distance | time | + | a | d | abcd | 300 +- 1m | 30s | + | d | a | abcd | 300 +- 1m | 55s | diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 3eb1ff339..341cb6d23 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -56,6 +56,12 @@ function way_function (way, numberOfNodesInWay) way.speed = speed_profile[highway] or speed_profile['default'] end + if(highway == "river") then + local temp_speed = way.speed; + way.speed = temp_speed*3/2 + way.backward_speed = temp_speed*2/3 + end + if oneway == "no" or oneway == "0" or oneway == "false" then way.direction = Way.bidirectional elseif oneway == "-1" then From fc24dbf9b7e423384aceefa5b058b80bf209f0fd Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 19:06:03 +0100 Subject: [PATCH 051/161] Added new TurnInstruction that indicates when to go against oneway streets. It's important for cycling. --- DataStructures/TurnInstructions.h | 41 +++---------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 2e709831d..66188f923 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -21,12 +21,12 @@ #ifndef TURNINSTRUCTIONS_H_ #define TURNINSTRUCTIONS_H_ -#include +#include typedef unsigned char TurnInstruction; //This is a hack until c++0x is available enough to use scoped enums -struct TurnInstructionsClass { +struct TurnInstructionsClass : boost::noncopyable { const static TurnInstruction NoTurn = 0; //Give no instruction at all const static TurnInstruction GoStraight = 1; //Tell user to go straight! @@ -44,48 +44,13 @@ struct TurnInstructionsClass { const static TurnInstruction StayOnRoundAbout = 13; const static TurnInstruction StartAtEndOfStreet = 14; const static TurnInstruction ReachedYourDestination = 15; + const static TurnInstruction GoAgainstAllowedDirection = 32; const static TurnInstruction AccessRestrictionFlag = 128; const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning. const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag -// std::string TurnStrings[16]; -// std::string Ordinals[12]; - - //This is a hack until c++0x is available enough to use initializer lists. -// TurnInstructionsClass(){ -// TurnStrings [0] = ""; -// TurnStrings [1] = "Continue"; -// TurnStrings [2] = "Turn slight right"; -// TurnStrings [3] = "Turn right"; -// TurnStrings [4] = "Turn sharp right"; -// TurnStrings [5] = "U-Turn"; -// TurnStrings [6] = "Turn sharp left"; -// TurnStrings [7] = "Turn left"; -// TurnStrings [8] = "Turn slight left"; -// TurnStrings [9] = "Reach via point"; -// TurnStrings[10] = "Head"; -// TurnStrings[11] = "Enter roundabout"; -// TurnStrings[12] = "Leave roundabout"; -// TurnStrings[13] = "Stay on roundabout"; -// TurnStrings[14] = "Start"; -// TurnStrings[15] = "You have reached your destination"; -// -// Ordinals[0] = "zeroth"; -// Ordinals[1] = "first"; -// Ordinals[2] = "second"; -// Ordinals[3] = "third"; -// Ordinals[4] = "fourth"; -// Ordinals[5] = "fifth"; -// Ordinals[6] = "sixth"; -// Ordinals[7] = "seventh"; -// Ordinals[8] = "eighth"; -// Ordinals[9] = "nineth"; -// Ordinals[10] = "tenth"; -// Ordinals[11] = "one of the too many"; -// }; - static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) { if(angle >= 23 && angle < 67) { return TurnSharpRight; From 9961172d70c9494807f4692e9cbd8d977a54a62e Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 19:33:51 +0100 Subject: [PATCH 052/161] Fixing constant --- DataStructures/TurnInstructions.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 66188f923..3284d9bbe 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -44,7 +44,8 @@ struct TurnInstructionsClass : boost::noncopyable { const static TurnInstruction StayOnRoundAbout = 13; const static TurnInstruction StartAtEndOfStreet = 14; const static TurnInstruction ReachedYourDestination = 15; - const static TurnInstruction GoAgainstAllowedDirection = 32; + const static TurnInstruction EnterAgainstAllowedDirection = 16; + const static TurnInstruction LeaveAgainstAllowedDirection = 17; const static TurnInstruction AccessRestrictionFlag = 128; const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning. From cf5c776990486d878254a48109d69122e46bf836 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 21:28:13 +0100 Subject: [PATCH 053/161] Implementing logic when route is going against one-way flow (think bikes!) --- Contractor/EdgeBasedGraphFactory.cpp | 15 ++++++- Contractor/EdgeBasedGraphFactory.h | 63 ++++++++++++++-------------- DataStructures/ImportEdge.h | 16 ++++--- Extractor/ExtractionContainers.cpp | 9 ++-- Extractor/ExtractionContainers.h | 2 +- Extractor/ExtractorCallbacks.cpp | 18 ++++---- Extractor/ExtractorCallbacks.h | 2 +- Extractor/ExtractorStructs.h | 62 +++++++++++++-------------- Extractor/PBFParser.cpp | 8 ++-- Extractor/PBFParser.h | 2 +- Extractor/ScriptingEnvironment.cpp | 24 +++++------ Extractor/XMLParser.cpp | 6 +-- Extractor/XMLParser.h | 4 +- Util/GraphLoader.h | 5 ++- extractor.cpp | 4 +- 15 files changed, 125 insertions(+), 115 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 994c4cc07..b6bc1e437 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -79,6 +79,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectortype(); edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.edgeBasedNodeID = edges.size(); + edge.data.contraFlow = i->isContraFlow(); edges.push_back( edge ); if( edge.data.backward ) { std::swap( edge.source, edge.target ); @@ -342,6 +343,13 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID _NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1); _NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2); + if(!data1.contraFlow && data2.contraFlow) { + return TurnInstructions.EnterAgainstAllowedDirection; + } + if(data1.contraFlow && !data2.contraFlow) { + return TurnInstructions.LeaveAgainstAllowedDirection; + } + //roundabouts need to be handled explicitely if(data1.roundabout && data2.roundabout) { //Is a turn possible? If yes, we stay on the roundabout! @@ -363,10 +371,13 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID } //If street names stay the same and if we are certain that it is not a roundabout, we skip it. - if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) + if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) { return TurnInstructions.NoTurn; - if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) + } + if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) { + ERR("should not happen"); return TurnInstructions.NoTurn; + } double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); return TurnInstructions.GetTurnDirectionOfInstruction(angle); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 2b4c18d7f..d4cc91888 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -48,34 +49,7 @@ #include "../DataStructures/TurnInstructions.h" #include "../Util/BaseConfiguration.h" -class EdgeBasedGraphFactory { -private: - struct _NodeBasedEdgeData { - int distance; - unsigned edgeBasedNodeID; - unsigned nameID; - short type; - bool isAccessRestricted; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool roundabout:1; - bool ignoreInGrid:1; - }; - - struct _EdgeBasedEdgeData { - int distance; - unsigned via; - unsigned nameID; - bool forward; - bool backward; - TurnInstruction turnInstruction; - }; - - typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; - typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; - std::vector inputNodeInfoList; - unsigned numberOfTurnRestrictions; +class EdgeBasedGraphFactory : boost::noncopyable { public: struct EdgeBasedNode { bool operator<(const EdgeBasedNode & other) const { @@ -95,13 +69,41 @@ public: bool ignoreInGrid:1; }; - struct SpeedProfileProperties{ SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {} int trafficSignalPenalty; int uTurnPenalty; } speedProfile; + private: + struct _NodeBasedEdgeData { + int distance; + unsigned edgeBasedNodeID; + unsigned nameID; + short type; + bool isAccessRestricted; + bool shortcut:1; + bool forward:1; + bool backward:1; + bool roundabout:1; + bool ignoreInGrid:1; + bool contraFlow; + }; + + struct _EdgeBasedEdgeData { + int distance; + unsigned via; + unsigned nameID; + bool forward; + bool backward; + TurnInstruction turnInstruction; + }; + + typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; + typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; + std::vector inputNodeInfoList; + unsigned numberOfTurnRestrictions; + boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph; boost::unordered_map _barrierNodes; boost::unordered_map _trafficLights; @@ -113,7 +115,6 @@ private: std::vector _restrictionBucketVector; RestrictionMap _restrictionMap; - DeallocatingVector edgeBasedEdges; DeallocatingVector edgeBasedNodes; std::vector originalEdgeData; @@ -127,8 +128,6 @@ private: bool belongsToTinyComponent); template double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const; -// SRTMLookup srtmLookup; - public: template< class InputEdgeT > diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index a90cd474d..1b5966c40 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -40,12 +40,8 @@ public: return (source() < e.source()); } - /** Default constructor. target and weight are set to 0.*/ - NodeBasedEdge() : - _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false) { assert(false); } //shall not be used. - - explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar) : - _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; } + explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -59,6 +55,7 @@ public: bool isRoundabout() const { return _roundabout; } bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } + bool isContraFlow() const { return _contraFlow; } NodeID _source; NodeID _target; @@ -70,6 +67,13 @@ public: bool _roundabout; bool _ignoreInGrid; bool _accessRestricted; + bool _contraFlow; + +private: + /** Default constructor. target and weight are set to 0.*/ + NodeBasedEdge() : + _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used. + }; class EdgeBasedEdge { diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index 93a0fd674..b2476bc86 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -231,17 +231,17 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->target, sizeof(unsigned)); fout.write((char*)&intDist, sizeof(int)); switch(edgeIT->direction) { - case _Way::notSure: + case ExtractionWay::notSure: fout.write((char*)&zero, sizeof(short)); break; - case _Way::oneway: + case ExtractionWay::oneway: fout.write((char*)&one, sizeof(short)); break; - case _Way::bidirectional: + case ExtractionWay::bidirectional: fout.write((char*)&zero, sizeof(short)); break; - case _Way::opposite: + case ExtractionWay::opposite: fout.write((char*)&one, sizeof(short)); break; default: @@ -256,6 +256,7 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->isRoundabout, sizeof(bool)); fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool)); fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool)); + fout.write((char*)&edgeIT->isContraFlow, sizeof(bool)); } ++usedEdgeCounter; ++edgeIT; diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h index 7e8a1d7be..abf718d5f 100644 --- a/Extractor/ExtractionContainers.h +++ b/Extractor/ExtractionContainers.h @@ -31,7 +31,7 @@ class ExtractionContainers { public: typedef stxxl::vector STXXLNodeIDVector; typedef stxxl::vector<_Node> STXXLNodeVector; - typedef stxxl::vector<_Edge> STXXLEdgeVector; + typedef stxxl::vector STXXLEdgeVector; typedef stxxl::vector STXXLStringVector; typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector; typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector; diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 75da55032..6a5ee1c14 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -64,7 +64,7 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { +bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { if ( parsed_way.speed > 0 ) { //Only true if the way is specified by the speed profile if(parsed_way.id == UINT_MAX){ WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); @@ -80,20 +80,20 @@ bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { parsed_way.nameID = string_map_iterator->second; } - if ( parsed_way.direction == _Way::opposite ){ + if ( parsed_way.direction == ExtractionWay::opposite ){ std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); } - if( parsed_way.backward_speed > 0 && parsed_way.direction == _Way::bidirectional) { - parsed_way.direction == _Way::oneway; + if( parsed_way.backward_speed > 0 && parsed_way.direction == ExtractionWay::bidirectional) { + parsed_way.direction = ExtractionWay::oneway; } for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( - _Edge(parsed_way.path[n], + InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n+1], parsed_way.type, - (_Way::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? _Way::oneway : parsed_way.direction), + (ExtractionWay::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? ExtractionWay::oneway : parsed_way.direction), parsed_way.speed, parsed_way.nameID, parsed_way.roundabout, @@ -113,17 +113,17 @@ bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( - _Edge(parsed_way.path[n], + InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n+1], parsed_way.type, - _Way::oneway, + ExtractionWay::oneway, parsed_way.backward_speed, parsed_way.nameID, parsed_way.roundabout, parsed_way.ignoreInGrid, parsed_way.isDurationSet, parsed_way.isAccessRestricted, - (_Way::oneway == parsed_way.direction) + (ExtractionWay::oneway == parsed_way.direction) ) ); } diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h index 70f812ec2..3ddbbe841 100644 --- a/Extractor/ExtractorCallbacks.h +++ b/Extractor/ExtractorCallbacks.h @@ -50,7 +50,7 @@ public: bool restrictionFunction(_RawRestrictionContainer &r); /** warning: caller needs to take care of synchronization! */ - bool wayFunction(_Way &w); + bool wayFunction(ExtractionWay &w); }; diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index ad508fdaf..c1ccbfe6e 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -40,8 +40,8 @@ or see http://www.gnu.org/licenses/agpl.txt. typedef boost::unordered_map StringMap; typedef boost::unordered_map > StringToIntPairMap; -struct _Way { - _Way() { +struct ExtractionWay { + ExtractionWay() { Clear(); } @@ -50,7 +50,7 @@ struct _Way { nameID = UINT_MAX; path.clear(); keyVals.EraseAll(); - direction = _Way::notSure; + direction = ExtractionWay::notSure; speed = -1; backward_speed = -1; type = -1; @@ -79,22 +79,22 @@ struct _Way { HashTable keyVals; }; -struct _Relation { - _Relation() : type(unknown){} +struct ExtractorRelation { + ExtractorRelation() : type(unknown){} enum { unknown = 0, ferry, turnRestriction } type; HashTable keyVals; }; -struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { +struct InternalExtractorEdge { + InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { assert(0 <= type); } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -112,15 +112,16 @@ struct _Edge { _Coordinate startCoord; _Coordinate targetCoord; - static _Edge min_value() { - return _Edge(0,0); + static InternalExtractorEdge min_value() { + return InternalExtractorEdge(0,0); } - static _Edge max_value() { - return _Edge((std::numeric_limits::max)(), (std::numeric_limits::max)()); + static InternalExtractorEdge max_value() { + return InternalExtractorEdge((std::numeric_limits::max)(), (std::numeric_limits::max)()); } - }; + + struct _WayIDStartAndEndEdge { unsigned wayID; NodeID firstStart; @@ -177,34 +178,29 @@ struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> { } }; -struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const { +struct CmpEdgeByStartID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.start < b.start; } value_type max_value() { - return _Edge::max_value(); + return InternalExtractorEdge::max_value(); } value_type min_value() { - return _Edge::min_value(); + return InternalExtractorEdge::min_value(); } }; -struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const - { +struct CmpEdgeByTargetID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.target < b.target; } - value_type max_value() - { - return _Edge::max_value(); + value_type max_value() { + return InternalExtractorEdge::max_value(); } - value_type min_value() - { - return _Edge::min_value(); + value_type min_value() { + return InternalExtractorEdge::min_value(); } }; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index d86fbc457..222475db6 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -332,8 +332,8 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { } inline void PBFParser::parseWay(_ThreadData * threadData) { - _Way w; - std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); + ExtractionWay w; + std::vector waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { w.Clear(); const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); @@ -356,7 +356,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { unsigned endi_ways = waysToParse.size(); #pragma omp parallel for schedule ( guided ) for(unsigned i = 0; i < endi_ways; ++i) { - _Way & w = waysToParse[i]; + ExtractionWay & w = waysToParse[i]; /** Pass the unpacked way to the LUA call back **/ try { luabind::call_function( @@ -376,7 +376,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { // } } - BOOST_FOREACH(_Way & w, waysToParse) { + BOOST_FOREACH(ExtractionWay & w, waysToParse) { if(!externalMemory->wayFunction(w)) { std::cerr << "[PBFParser] way not parsed" << std::endl; } diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index ed469272d..d3da02706 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -41,7 +41,7 @@ #include "ExtractorStructs.h" #include "ScriptingEnvironment.h" -class PBFParser : public BaseParser { +class PBFParser : public BaseParser { enum EntityType { TypeNode = 1, diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index b4b6af54e..ca8d9a754 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -65,19 +65,19 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ]; luabind::module(myLuaState) [ - luabind::class_<_Way>("Way") + luabind::class_("Way") .def(luabind::constructor<>()) - .def_readwrite("name", &_Way::name) - .def_readwrite("backward_speed", &_Way::backward_speed) - .def_readwrite("speed", &_Way::speed) - .def_readwrite("type", &_Way::type) - .def_readwrite("access", &_Way::access) - .def_readwrite("roundabout", &_Way::roundabout) - .def_readwrite("is_duration_set", &_Way::isDurationSet) - .def_readwrite("is_access_restricted", &_Way::isAccessRestricted) - .def_readwrite("ignore_in_grid", &_Way::ignoreInGrid) - .def_readwrite("tags", &_Way::keyVals) - .def_readwrite("direction", &_Way::direction) + .def_readwrite("name", &ExtractionWay::name) + .def_readwrite("backward_speed", &ExtractionWay::backward_speed) + .def_readwrite("speed", &ExtractionWay::speed) + .def_readwrite("type", &ExtractionWay::type) + .def_readwrite("access", &ExtractionWay::access) + .def_readwrite("roundabout", &ExtractionWay::roundabout) + .def_readwrite("is_duration_set", &ExtractionWay::isDurationSet) + .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted) + .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) + .def_readwrite("tags", &ExtractionWay::keyVals) + .def_readwrite("direction", &ExtractionWay::direction) .enum_("constants") [ luabind::value("notSure", 0), diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 6449add3f..5faa5a71e 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -100,7 +100,7 @@ bool XMLParser::Parse() { } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - _Way way = _ReadXMLWay( ); + ExtractionWay way = _ReadXMLWay( ); /** Pass the unpacked way to the LUA call back **/ try { @@ -222,8 +222,8 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { return restriction; } -_Way XMLParser::_ReadXMLWay() { - _Way way; +ExtractionWay XMLParser::_ReadXMLWay() { + ExtractionWay way; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index d87c50145..3bc54825d 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -28,7 +28,7 @@ #include "ExtractorCallbacks.h" #include "ScriptingEnvironment.h" -class XMLParser : public BaseParser { +class XMLParser : public BaseParser { public: XMLParser(const char * filename); virtual ~XMLParser(); @@ -39,7 +39,7 @@ public: private: _RawRestrictionContainer _ReadXMLRestriction(); - _Way _ReadXMLWay(); + ExtractionWay _ReadXMLWay(); ImportNode _ReadXMLNode( ); /* Input Reader */ xmlTextReaderPtr inputReader; diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index b22086c39..40bc98a9c 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -101,7 +101,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL short type; NodeID nameID; int length; - bool isRoundabout, ignoreInGrid, isAccessRestricted; + bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; for (EdgeID i=0; i& edgeL in.read((char*)&isRoundabout, sizeof(bool)); in.read((char*)&ignoreInGrid, sizeof(bool)); in.read((char*)&isAccessRestricted, sizeof(bool)); + in.read((char*)&isContraFlow, sizeof(bool)); GUARANTEE(length > 0, "loaded null length edge" ); GUARANTEE(weight > 0, "loaded null weight"); @@ -150,7 +151,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL std::swap(forward, backward); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); edgeList.push_back(inputEdge); } std::sort(edgeList.begin(), edgeList.end()); diff --git a/extractor.cpp b/extractor.cpp index d212a837e..1aa72f83b 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -58,7 +58,6 @@ int main (int argc, char *argv[]) { } omp_set_num_threads(numberOfThreads); - INFO("extracting data from input file " << argv[1]); bool isPBF(false); std::string outputFileName(argv[1]); @@ -93,10 +92,9 @@ int main (int argc, char *argv[]) { StringMap stringMap; ExtractionContainers externalMemory; - stringMap[""] = 0; extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap); - BaseParser * parser; + BaseParser * parser; if(isPBF) { parser = new PBFParser(argv[1]); } else { From 35255d052d70b8698534cff02c24c8cec09b9398 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 12 Jan 2013 19:15:08 +0100 Subject: [PATCH 054/161] support comments in test tables --- features/step_definitions/routing.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 32e6f60e5..17a3251c0 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -46,6 +46,9 @@ When /^I route I should get$/ do |table| if table.headers.include? 'turns' got['turns'] = turns end + if table.headers.include? '#' # comment column + got['#'] = row['#'] # copy value so it always match + end end ok = true From 7c8bf18cc6929db04b88acf6336979efa196d057 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 18 Jan 2013 22:10:11 +0100 Subject: [PATCH 055/161] test forward/backward maxspeed (car) --- features/car/maxspeed.feature | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index cc31c6c13..abdb72a9e 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -32,3 +32,26 @@ Feature: Car - Max speed restrictions | from | to | route | time | | a | b | ab | 144s ~10% | | b | c | bc | 144s ~10% | + + @oppposite @todo + Scenario: Car - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | + + And the ways + | nodes | highway | maxspeed:forward | maxspeed:backward | + | ab | primary | | | + | bc | primart | 18 | 9 | + | cd | primart | | 9 | + | de | primart | 9 | | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s | + | b | a | ab | 10s | + | b | c | bc | 20s | + | c | b | bc | 40s | + | c | d | cd | 10s | + | d | c | cd | 20s | + | d | e | de | 20s | + | e | d | de | 10s | From 46d1a87b89db7300ffe3ff5de9e8b84e91d71fc5 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 18 Jan 2013 22:11:22 +0100 Subject: [PATCH 056/161] fix tag on @opposite test --- features/testbot/opposite.feature | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 9b5df779d..bcc4567d3 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -4,8 +4,7 @@ Feature: Separate settings for forward/backward direction Background: Given the profile "testbot" - @smallest - Scenario: Going against the flow + Scenario: Testbot - Going against the flow Given the node map | a | b | c | d | @@ -16,4 +15,4 @@ Feature: Separate settings for forward/backward direction When I route I should get | from | to | route | distance | time | | a | d | abcd | 300 +- 1m | 30s | - | d | a | abcd | 300 +- 1m | 55s | + | d | a | abcd | 300 +- 1m | 55s | \ No newline at end of file From 384be58230fb36d8fbbbec519dd2b7582cdb8d05 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 19 Jan 2013 13:04:58 +0100 Subject: [PATCH 057/161] test maxspeed forward/backward --- features/car/maxspeed.feature | 31 ++------------ features/testbot/maxspeed.feature | 70 +++++++++++++++++++++++++++++++ features/testbot/opposite.feature | 2 +- profiles/testbot.lua | 41 +++++++++++++++--- 4 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 features/testbot/maxspeed.feature diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index abdb72a9e..8e40e95bf 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -10,9 +10,9 @@ Feature: Car - Max speed restrictions | a | b | c | And the ways - | nodes | highway | maxspeed | - | ab | trunk | | - | bc | trunk | 10 | + | nodes | highway | maxspeed | + | ab | trunk | | + | bc | trunk | 10 | When I route I should get | from | to | route | time | @@ -31,27 +31,4 @@ Feature: Car - Max speed restrictions When I route I should get | from | to | route | time | | a | b | ab | 144s ~10% | - | b | c | bc | 144s ~10% | - - @oppposite @todo - Scenario: Car - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | - - And the ways - | nodes | highway | maxspeed:forward | maxspeed:backward | - | ab | primary | | | - | bc | primart | 18 | 9 | - | cd | primart | | 9 | - | de | primart | 9 | | - - When I route I should get - | from | to | route | time | - | a | b | ab | 10s | - | b | a | ab | 10s | - | b | c | bc | 20s | - | c | b | bc | 40s | - | c | d | cd | 10s | - | d | c | cd | 20s | - | d | e | de | 20s | - | e | d | de | 10s | + | b | c | bc | 144s ~10% | diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature new file mode 100644 index 000000000..4f454be70 --- /dev/null +++ b/features/testbot/maxspeed.feature @@ -0,0 +1,70 @@ +@routing @maxspeed @testbot +Feature: Car - Max speed restrictions + + Background: Use specific speeds + Given the profile "testbot" + + Scenario: Testbot - Respect maxspeeds when lower that way type speed + Given the node map + | a | b | c | d | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 24 | + | cd | 18 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 15s +-1 | + | c | b | bc | 15s +-1 | + | c | d | cd | 20s +-1 | + | d | c | cd | 20s +-1 | + + Scenario: Testbot - Ignore maxspeed when higher than way speed + Given the node map + | a | b | c | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 200 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 20s +-1 | + | b | c | bc | 20s +-1 | + + @opposite + Scenario: Testbot - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | f | g | h | + + And the ways + | nodes | maxspeed | maxspeed:forward | maxspeed:backward | + | ab | | | | + | bc | 18 | | | + | cd | | 18 | | + | de | | | 18 | + | ef | 9 | 18 | | + | fg | 9 | | 18 | + | gh | 9 | 24 | 18 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 20s +-1 | + | c | b | bc | 20s +-1 | + | c | d | cd | 20s +-1 | + | d | c | cd | 10s +-1 | + | d | e | de | 10s +-1 | + | e | d | de | 20s +-1 | + | e | f | ef | 20s +-1 | + | f | e | ef | 10s +-1 | + | f | g | fg | 10s +-1 | + | g | f | fg | 20s +-1 | + | g | h | gh | 15s +-1 | + | h | g | gh | 10s +-1 | diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index bcc4567d3..fb73c6649 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,4 +1,4 @@ -@routing @opposite +@routing @testbot @opposite Feature: Separate settings for forward/backward direction Background: diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 341cb6d23..2c13a4e5b 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -23,6 +23,18 @@ ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 +function limit_speed(speed, limits) + -- don't use ipairs(), since it stops at the first nil value + for i=1, #limits do + limit = limits[i] + if limit ~= nil and limit > 0 then + if limit < speed then + return limit -- stop at first speedlimit that's smaller than speed + end + end + end + return speed +end function node_function (node) local traffic_signal = node.tags:Find("highway") @@ -45,6 +57,15 @@ function way_function (way, numberOfNodesInWay) local oneway = way.tags:Find("oneway") local route = way.tags:Find("route") local duration = way.tags:Find("duration") + local maxspeed = tonumber(way.tags:Find ( "maxspeed")) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) + + print('---') + print(name) + print(tostring(maxspeed)) + print(tostring(maxspeed_forward)) + print(tostring(maxspeed_backward)) way.name = name @@ -54,12 +75,20 @@ function way_function (way, numberOfNodesInWay) way.is_duration_set = true else way.speed = speed_profile[highway] or speed_profile['default'] - end - - if(highway == "river") then - local temp_speed = way.speed; - way.speed = temp_speed*3/2 - way.backward_speed = temp_speed*2/3 + + if highway == "river" then + local temp_speed = way.speed; + way.speed = temp_speed*3/2 + way.backward_speed = temp_speed*2/3 + else + way.backward_speed = way.speed + end + + way.speed = limit_speed( way.speed, {maxspeed_forward, maxspeed} ) + way.backward_speed = limit_speed( way.backward_speed, {maxspeed_backward, maxspeed} ) + + -- print( 'limit forw: ' .. tostring(way.speed)) + -- print( 'limit back: ' .. tostring(way.backward_speed)) end if oneway == "no" or oneway == "0" or oneway == "false" then From 43bb53e7891f632358d4db595424f9f6fceabde7 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 19 Jan 2013 16:00:36 +0100 Subject: [PATCH 058/161] better testbot maxspeed handling, fix test --- features/testbot/maxspeed.feature | 6 ++++-- profiles/testbot.lua | 22 +++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature index 4f454be70..1d40233a5 100644 --- a/features/testbot/maxspeed.feature +++ b/features/testbot/maxspeed.feature @@ -34,8 +34,10 @@ Feature: Car - Max speed restrictions When I route I should get | from | to | route | time | - | a | b | ab | 20s +-1 | - | b | c | bc | 20s +-1 | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 10s +-1 | + | c | b | bc | 10s +-1 | @opposite Scenario: Testbot - Forward/backward maxspeed diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 2c13a4e5b..82489850a 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -74,21 +74,25 @@ function way_function (way, numberOfNodesInWay) way.speed = math.max( 1, parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ) way.is_duration_set = true else - way.speed = speed_profile[highway] or speed_profile['default'] + local speed_forw = speed_profile[highway] or speed_profile['default'] + local speed_back = speed_forw if highway == "river" then local temp_speed = way.speed; - way.speed = temp_speed*3/2 - way.backward_speed = temp_speed*2/3 - else - way.backward_speed = way.speed + speed_forw = temp_speed*3/2 + speed_back = temp_speed*2/3 end + + speed_forw = limit_speed( speed_forw, {maxspeed_forward, maxspeed} ) + speed_back = limit_speed( speed_back, {maxspeed_backward, maxspeed} ) - way.speed = limit_speed( way.speed, {maxspeed_forward, maxspeed} ) - way.backward_speed = limit_speed( way.backward_speed, {maxspeed_backward, maxspeed} ) + way.speed = speed_forw + if speed_back ~= way_forw then + way.backward_speed = speed_back + end - -- print( 'limit forw: ' .. tostring(way.speed)) - -- print( 'limit back: ' .. tostring(way.backward_speed)) + -- print( 'speed forw: ' .. tostring(way.speed)) + -- print( 'speed back: ' .. tostring(way.backward_speed)) end if oneway == "no" or oneway == "0" or oneway == "false" then From 296e7ccb08fc297cac223dc1412ff0585e73859a Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 23 Jan 2013 11:34:16 +0100 Subject: [PATCH 059/161] Removing dead code --- Contractor/EdgeBasedGraphFactory.cpp | 4 ---- Contractor/EdgeBasedGraphFactory.h | 3 --- createHierarchy.cpp | 6 ++---- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 994c4cc07..4126cff01 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -108,10 +108,6 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode nodes.swap(edgeBasedNodes); } -void EdgeBasedGraphFactory::GetOriginalEdgeData( std::vector< OriginalEdgeData> & oed) { - oed.swap(originalEdgeData); -} - NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const { std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v); RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 2b4c18d7f..0b909b264 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -127,8 +127,6 @@ private: bool belongsToTinyComponent); template double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const; -// SRTMLookup srtmLookup; - public: template< class InputEdgeT > @@ -137,7 +135,6 @@ public: void Run(const char * originalEdgeDataFilename); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes); - void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData); TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const; unsigned GetNumberOfNodes() const; }; diff --git a/createHierarchy.cpp b/createHierarchy.cpp index a638fcd18..87e9105c4 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -171,10 +171,6 @@ int main (int argc, char *argv[]) { /*** * Writing info on original (node-based) edges */ - INFO("writing info on original edges"); - std::vector originalEdgeData; - edgeBasedGraphFactory->GetOriginalEdgeData(originalEdgeData); - DeallocatingVector nodeBasedEdgeList; edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); delete edgeBasedGraphFactory; @@ -274,5 +270,7 @@ int main (int argc, char *argv[]) { //cleanedEdgeList.clear(); _nodes.clear(); INFO("finished preprocessing"); + + INFO("Edgebased edge list size " << edgeBasedEdgeList.size()); return 0; } From b4ee3459665c08df3780dfcd1b21c7952513bee8 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 23 Jan 2013 11:52:18 +0100 Subject: [PATCH 060/161] removing left-over debug output --- createHierarchy.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 87e9105c4..066261a4e 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -270,7 +270,5 @@ int main (int argc, char *argv[]) { //cleanedEdgeList.clear(); _nodes.clear(); INFO("finished preprocessing"); - - INFO("Edgebased edge list size " << edgeBasedEdgeList.size()); return 0; } From cbea651cf8ccc2a44380039731485e3f29c37c90 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 26 Jan 2013 18:58:33 +0100 Subject: [PATCH 061/161] test duration on ways --- features/testbot/duration.feature | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 features/testbot/duration.feature diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature new file mode 100644 index 000000000..088f938d6 --- /dev/null +++ b/features/testbot/duration.feature @@ -0,0 +1,25 @@ +@routing @testbot @routes @duration +Feature: OSM Route Relation + + Background: + Given the profile "testbot" + + Scenario: Duration of ways + Given the node map + | a | b | | | | + | | | | e | | + | | c | | | d | + + And the ways + | nodes | highway | duration | + | ab | primary | 0:01 | + | bc | primary | 0:10 | + | cd | primary | 1:00 | + | de | primary | 10:00 | + + When I route I should get + | from | to | route | distance | time | + | a | b | ab | 100m +-1 | 1s +-1 | + | b | c | bc | 200m +-1 | 10s +-1 | + | c | d | cd | 300m +-1 | 60s +-1 | + | d | e | de | 144m +-1 | 600s +-1 | From c68a03d05c4f997ecda7a1f1272e329d559d5400 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 26 Jan 2013 18:59:31 +0100 Subject: [PATCH 062/161] add test scenario matching wiki graph explanation --- features/testbot/graph.feature | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 features/testbot/graph.feature diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature new file mode 100644 index 000000000..97a517119 --- /dev/null +++ b/features/testbot/graph.feature @@ -0,0 +1,22 @@ +@routing @graph +Feature: Basic Routing +Test the input data descibed on https://github.com/DennisOSRM/Project-OSRM/wiki/Graph-representation + + Background: + Given the profile "testbot" + + @smallest + Scenario: Graph transformation + Given the node map + | | | d | + | a | b | c | + | | | e | + + And the ways + | nodes | + | abc | + | dce | + + When I route I should get + | from | to | route | + | a | e | abc,dce | From aa9d8c773f2cf94bf70ad13596c8ec0a09242160 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 26 Jan 2013 19:06:23 +0100 Subject: [PATCH 063/161] fix name of duration test --- features/testbot/duration.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature index 088f938d6..67bbe559d 100644 --- a/features/testbot/duration.feature +++ b/features/testbot/duration.feature @@ -1,5 +1,5 @@ @routing @testbot @routes @duration -Feature: OSM Route Relation +Feature: Durations Background: Given the profile "testbot" From b069725df062c43ddbcb4e1f4184bb9e26ecbc1b Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:40:12 +0100 Subject: [PATCH 064/161] Support for backward speed in extractor --- Extractor/ExtractorCallbacks.cpp | 99 +++++++++++++++++++----------- Extractor/ExtractorStructs.h | 14 +++-- Extractor/ScriptingEnvironment.cpp | 1 + 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 3db1d8d8b..75da55032 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -44,8 +44,8 @@ or see http://www.gnu.org/licenses/agpl.txt. ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; } ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) { - externalMemory = ext; - stringMap = strMap; + externalMemory = ext; + stringMap = strMap; } ExtractorCallbacks::~ExtractorCallbacks() { @@ -64,42 +64,71 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &w) { - /*** Store name of way and split it into edge segments ***/ +bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { + if ( parsed_way.speed > 0 ) { //Only true if the way is specified by the speed profile + if(parsed_way.id == UINT_MAX){ + WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); + return true; + } + //Get the unique identifier for the street name + const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); + if(string_map_iterator == stringMap->end()) { + parsed_way.nameID = externalMemory->nameVector.size(); + externalMemory->nameVector.push_back(parsed_way.name); + stringMap->insert(StringMap::value_type(parsed_way.name, parsed_way.nameID)); + } else { + parsed_way.nameID = string_map_iterator->second; + } - if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile + if ( parsed_way.direction == _Way::opposite ){ + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + } - //Get the unique identifier for the street name - const StringMap::const_iterator strit = stringMap->find(w.name); - if(strit == stringMap->end()) { - w.nameID = externalMemory->nameVector.size(); - externalMemory->nameVector.push_back(w.name); - stringMap->insert(StringMap::value_type(w.name, w.nameID)); - } else { - w.nameID = strit->second; - } + if( parsed_way.backward_speed > 0 && parsed_way.direction == _Way::bidirectional) { + parsed_way.direction == _Way::oneway; + } - if(fabs(-1. - w.speed) < FLT_EPSILON){ - WARN("found way with bogus speed, id: " << w.id); - return true; - } - if(w.id == UINT_MAX) { - WARN("found way with unknown type: " << w.id); - return true; - } + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + (_Way::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? _Way::oneway : parsed_way.direction), + parsed_way.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted + ) + ); + externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); + } + externalMemory->usedNodeIDs.push_back(parsed_way.path.back()); - if ( w.direction == _Way::opposite ){ - std::reverse( w.path.begin(), w.path.end() ); - } + //The following information is needed to identify start and end segments of restrictions + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); - for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted)); - externalMemory->usedNodeIDs.push_back(w.path[n]); - } - externalMemory->usedNodeIDs.push_back(w.path.back()); - - //The following information is needed to identify start and end segments of restrictions - externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1])); - } - return true; + if ( parsed_way.backward_speed > 0 ) { //Only true if the way should be split + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + _Edge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + _Way::oneway, + parsed_way.backward_speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.isDurationSet, + parsed_way.isAccessRestricted, + (_Way::oneway == parsed_way.direction) + ) + ); + } + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); + } + } + return true; } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe5dd1b40..ad508fdaf 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -52,6 +52,7 @@ struct _Way { keyVals.EraseAll(); direction = _Way::notSure; speed = -1; + backward_speed = -1; type = -1; access = true; roundabout = false; @@ -67,6 +68,7 @@ struct _Way { unsigned nameID; std::string name; double speed; + double backward_speed; short type; bool access; bool roundabout; @@ -86,10 +88,13 @@ struct _Relation { }; struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) { + _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { + assert(0 <= type); + } + _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -102,6 +107,7 @@ struct _Edge { bool ignoreInGrid; bool isDurationSet; bool isAccessRestricted; + bool isContraFlow; _Coordinate startCoord; _Coordinate targetCoord; diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index c2f42d79d..b4b6af54e 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -68,6 +68,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::class_<_Way>("Way") .def(luabind::constructor<>()) .def_readwrite("name", &_Way::name) + .def_readwrite("backward_speed", &_Way::backward_speed) .def_readwrite("speed", &_Way::speed) .def_readwrite("type", &_Way::type) .def_readwrite("access", &_Way::access) From 7b4b7232fcc8936e2639583dc2e460db59939318 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 16:42:04 +0100 Subject: [PATCH 065/161] Fixing test for opposite directions --- features/testbot/opposite.feature | 12 ++++++------ profiles/testbot.lua | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 176974965..9b5df779d 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,4 +1,4 @@ -@routing @opposite @todo +@routing @opposite Feature: Separate settings for forward/backward direction Background: @@ -7,13 +7,13 @@ Feature: Separate settings for forward/backward direction @smallest Scenario: Going against the flow Given the node map - | a | b | + | a | b | c | d | And the ways | nodes | highway | - | ab | river | + | abcd | river | When I route I should get - | from | to | route | distance | time | - | a | b | ab | 100m | 10s | - | b | a | ab | 100m | 20s | + | from | to | route | distance | time | + | a | d | abcd | 300 +- 1m | 30s | + | d | a | abcd | 300 +- 1m | 55s | diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 3eb1ff339..341cb6d23 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -56,6 +56,12 @@ function way_function (way, numberOfNodesInWay) way.speed = speed_profile[highway] or speed_profile['default'] end + if(highway == "river") then + local temp_speed = way.speed; + way.speed = temp_speed*3/2 + way.backward_speed = temp_speed*2/3 + end + if oneway == "no" or oneway == "0" or oneway == "false" then way.direction = Way.bidirectional elseif oneway == "-1" then From dd1302e8b114fd8acd7119133e6b97a5158b4121 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 19:06:03 +0100 Subject: [PATCH 066/161] Added new TurnInstruction that indicates when to go against oneway streets. It's important for cycling. --- DataStructures/TurnInstructions.h | 41 +++---------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 2e709831d..66188f923 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -21,12 +21,12 @@ #ifndef TURNINSTRUCTIONS_H_ #define TURNINSTRUCTIONS_H_ -#include +#include typedef unsigned char TurnInstruction; //This is a hack until c++0x is available enough to use scoped enums -struct TurnInstructionsClass { +struct TurnInstructionsClass : boost::noncopyable { const static TurnInstruction NoTurn = 0; //Give no instruction at all const static TurnInstruction GoStraight = 1; //Tell user to go straight! @@ -44,48 +44,13 @@ struct TurnInstructionsClass { const static TurnInstruction StayOnRoundAbout = 13; const static TurnInstruction StartAtEndOfStreet = 14; const static TurnInstruction ReachedYourDestination = 15; + const static TurnInstruction GoAgainstAllowedDirection = 32; const static TurnInstruction AccessRestrictionFlag = 128; const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning. const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag -// std::string TurnStrings[16]; -// std::string Ordinals[12]; - - //This is a hack until c++0x is available enough to use initializer lists. -// TurnInstructionsClass(){ -// TurnStrings [0] = ""; -// TurnStrings [1] = "Continue"; -// TurnStrings [2] = "Turn slight right"; -// TurnStrings [3] = "Turn right"; -// TurnStrings [4] = "Turn sharp right"; -// TurnStrings [5] = "U-Turn"; -// TurnStrings [6] = "Turn sharp left"; -// TurnStrings [7] = "Turn left"; -// TurnStrings [8] = "Turn slight left"; -// TurnStrings [9] = "Reach via point"; -// TurnStrings[10] = "Head"; -// TurnStrings[11] = "Enter roundabout"; -// TurnStrings[12] = "Leave roundabout"; -// TurnStrings[13] = "Stay on roundabout"; -// TurnStrings[14] = "Start"; -// TurnStrings[15] = "You have reached your destination"; -// -// Ordinals[0] = "zeroth"; -// Ordinals[1] = "first"; -// Ordinals[2] = "second"; -// Ordinals[3] = "third"; -// Ordinals[4] = "fourth"; -// Ordinals[5] = "fifth"; -// Ordinals[6] = "sixth"; -// Ordinals[7] = "seventh"; -// Ordinals[8] = "eighth"; -// Ordinals[9] = "nineth"; -// Ordinals[10] = "tenth"; -// Ordinals[11] = "one of the too many"; -// }; - static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) { if(angle >= 23 && angle < 67) { return TurnSharpRight; From 4a52dd1c5be5e1993aa2c0de422e3c2bdc8642ec Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 19:33:51 +0100 Subject: [PATCH 067/161] Fixing constant --- DataStructures/TurnInstructions.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 66188f923..3284d9bbe 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -44,7 +44,8 @@ struct TurnInstructionsClass : boost::noncopyable { const static TurnInstruction StayOnRoundAbout = 13; const static TurnInstruction StartAtEndOfStreet = 14; const static TurnInstruction ReachedYourDestination = 15; - const static TurnInstruction GoAgainstAllowedDirection = 32; + const static TurnInstruction EnterAgainstAllowedDirection = 16; + const static TurnInstruction LeaveAgainstAllowedDirection = 17; const static TurnInstruction AccessRestrictionFlag = 128; const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning. From e6e5626a2c3d853ff945a8c78c25122b12057656 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 18 Jan 2013 21:28:13 +0100 Subject: [PATCH 068/161] Implementing logic when route is going against one-way flow (think bikes!) --- Contractor/EdgeBasedGraphFactory.cpp | 15 ++++++- Contractor/EdgeBasedGraphFactory.h | 63 ++++++++++++++-------------- DataStructures/ImportEdge.h | 16 ++++--- Extractor/ExtractionContainers.cpp | 9 ++-- Extractor/ExtractionContainers.h | 2 +- Extractor/ExtractorCallbacks.cpp | 18 ++++---- Extractor/ExtractorCallbacks.h | 2 +- Extractor/ExtractorStructs.h | 62 +++++++++++++-------------- Extractor/PBFParser.cpp | 8 ++-- Extractor/PBFParser.h | 2 +- Extractor/ScriptingEnvironment.cpp | 24 +++++------ Extractor/XMLParser.cpp | 6 +-- Extractor/XMLParser.h | 4 +- Util/GraphLoader.h | 5 ++- extractor.cpp | 4 +- 15 files changed, 125 insertions(+), 115 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 994c4cc07..b6bc1e437 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -79,6 +79,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectortype(); edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.edgeBasedNodeID = edges.size(); + edge.data.contraFlow = i->isContraFlow(); edges.push_back( edge ); if( edge.data.backward ) { std::swap( edge.source, edge.target ); @@ -342,6 +343,13 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID _NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1); _NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2); + if(!data1.contraFlow && data2.contraFlow) { + return TurnInstructions.EnterAgainstAllowedDirection; + } + if(data1.contraFlow && !data2.contraFlow) { + return TurnInstructions.LeaveAgainstAllowedDirection; + } + //roundabouts need to be handled explicitely if(data1.roundabout && data2.roundabout) { //Is a turn possible? If yes, we stay on the roundabout! @@ -363,10 +371,13 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID } //If street names stay the same and if we are certain that it is not a roundabout, we skip it. - if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) + if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) { return TurnInstructions.NoTurn; - if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) + } + if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) { + ERR("should not happen"); return TurnInstructions.NoTurn; + } double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); return TurnInstructions.GetTurnDirectionOfInstruction(angle); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 2b4c18d7f..d4cc91888 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -48,34 +49,7 @@ #include "../DataStructures/TurnInstructions.h" #include "../Util/BaseConfiguration.h" -class EdgeBasedGraphFactory { -private: - struct _NodeBasedEdgeData { - int distance; - unsigned edgeBasedNodeID; - unsigned nameID; - short type; - bool isAccessRestricted; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool roundabout:1; - bool ignoreInGrid:1; - }; - - struct _EdgeBasedEdgeData { - int distance; - unsigned via; - unsigned nameID; - bool forward; - bool backward; - TurnInstruction turnInstruction; - }; - - typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; - typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; - std::vector inputNodeInfoList; - unsigned numberOfTurnRestrictions; +class EdgeBasedGraphFactory : boost::noncopyable { public: struct EdgeBasedNode { bool operator<(const EdgeBasedNode & other) const { @@ -95,13 +69,41 @@ public: bool ignoreInGrid:1; }; - struct SpeedProfileProperties{ SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {} int trafficSignalPenalty; int uTurnPenalty; } speedProfile; + private: + struct _NodeBasedEdgeData { + int distance; + unsigned edgeBasedNodeID; + unsigned nameID; + short type; + bool isAccessRestricted; + bool shortcut:1; + bool forward:1; + bool backward:1; + bool roundabout:1; + bool ignoreInGrid:1; + bool contraFlow; + }; + + struct _EdgeBasedEdgeData { + int distance; + unsigned via; + unsigned nameID; + bool forward; + bool backward; + TurnInstruction turnInstruction; + }; + + typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; + typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; + std::vector inputNodeInfoList; + unsigned numberOfTurnRestrictions; + boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph; boost::unordered_map _barrierNodes; boost::unordered_map _trafficLights; @@ -113,7 +115,6 @@ private: std::vector _restrictionBucketVector; RestrictionMap _restrictionMap; - DeallocatingVector edgeBasedEdges; DeallocatingVector edgeBasedNodes; std::vector originalEdgeData; @@ -127,8 +128,6 @@ private: bool belongsToTinyComponent); template double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const; -// SRTMLookup srtmLookup; - public: template< class InputEdgeT > diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index a90cd474d..1b5966c40 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -40,12 +40,8 @@ public: return (source() < e.source()); } - /** Default constructor. target and weight are set to 0.*/ - NodeBasedEdge() : - _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false) { assert(false); } //shall not be used. - - explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar) : - _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; } + explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -59,6 +55,7 @@ public: bool isRoundabout() const { return _roundabout; } bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } + bool isContraFlow() const { return _contraFlow; } NodeID _source; NodeID _target; @@ -70,6 +67,13 @@ public: bool _roundabout; bool _ignoreInGrid; bool _accessRestricted; + bool _contraFlow; + +private: + /** Default constructor. target and weight are set to 0.*/ + NodeBasedEdge() : + _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used. + }; class EdgeBasedEdge { diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index 93a0fd674..b2476bc86 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -231,17 +231,17 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->target, sizeof(unsigned)); fout.write((char*)&intDist, sizeof(int)); switch(edgeIT->direction) { - case _Way::notSure: + case ExtractionWay::notSure: fout.write((char*)&zero, sizeof(short)); break; - case _Way::oneway: + case ExtractionWay::oneway: fout.write((char*)&one, sizeof(short)); break; - case _Way::bidirectional: + case ExtractionWay::bidirectional: fout.write((char*)&zero, sizeof(short)); break; - case _Way::opposite: + case ExtractionWay::opposite: fout.write((char*)&one, sizeof(short)); break; default: @@ -256,6 +256,7 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->isRoundabout, sizeof(bool)); fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool)); fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool)); + fout.write((char*)&edgeIT->isContraFlow, sizeof(bool)); } ++usedEdgeCounter; ++edgeIT; diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h index 7e8a1d7be..abf718d5f 100644 --- a/Extractor/ExtractionContainers.h +++ b/Extractor/ExtractionContainers.h @@ -31,7 +31,7 @@ class ExtractionContainers { public: typedef stxxl::vector STXXLNodeIDVector; typedef stxxl::vector<_Node> STXXLNodeVector; - typedef stxxl::vector<_Edge> STXXLEdgeVector; + typedef stxxl::vector STXXLEdgeVector; typedef stxxl::vector STXXLStringVector; typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector; typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector; diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 75da55032..6a5ee1c14 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -64,7 +64,7 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { +bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { if ( parsed_way.speed > 0 ) { //Only true if the way is specified by the speed profile if(parsed_way.id == UINT_MAX){ WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); @@ -80,20 +80,20 @@ bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { parsed_way.nameID = string_map_iterator->second; } - if ( parsed_way.direction == _Way::opposite ){ + if ( parsed_way.direction == ExtractionWay::opposite ){ std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); } - if( parsed_way.backward_speed > 0 && parsed_way.direction == _Way::bidirectional) { - parsed_way.direction == _Way::oneway; + if( parsed_way.backward_speed > 0 && parsed_way.direction == ExtractionWay::bidirectional) { + parsed_way.direction = ExtractionWay::oneway; } for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( - _Edge(parsed_way.path[n], + InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n+1], parsed_way.type, - (_Way::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? _Way::oneway : parsed_way.direction), + (ExtractionWay::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? ExtractionWay::oneway : parsed_way.direction), parsed_way.speed, parsed_way.nameID, parsed_way.roundabout, @@ -113,17 +113,17 @@ bool ExtractorCallbacks::wayFunction(_Way &parsed_way) { std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( - _Edge(parsed_way.path[n], + InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n+1], parsed_way.type, - _Way::oneway, + ExtractionWay::oneway, parsed_way.backward_speed, parsed_way.nameID, parsed_way.roundabout, parsed_way.ignoreInGrid, parsed_way.isDurationSet, parsed_way.isAccessRestricted, - (_Way::oneway == parsed_way.direction) + (ExtractionWay::oneway == parsed_way.direction) ) ); } diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h index 70f812ec2..3ddbbe841 100644 --- a/Extractor/ExtractorCallbacks.h +++ b/Extractor/ExtractorCallbacks.h @@ -50,7 +50,7 @@ public: bool restrictionFunction(_RawRestrictionContainer &r); /** warning: caller needs to take care of synchronization! */ - bool wayFunction(_Way &w); + bool wayFunction(ExtractionWay &w); }; diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index ad508fdaf..c1ccbfe6e 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -40,8 +40,8 @@ or see http://www.gnu.org/licenses/agpl.txt. typedef boost::unordered_map StringMap; typedef boost::unordered_map > StringToIntPairMap; -struct _Way { - _Way() { +struct ExtractionWay { + ExtractionWay() { Clear(); } @@ -50,7 +50,7 @@ struct _Way { nameID = UINT_MAX; path.clear(); keyVals.EraseAll(); - direction = _Way::notSure; + direction = ExtractionWay::notSure; speed = -1; backward_speed = -1; type = -1; @@ -79,22 +79,22 @@ struct _Way { HashTable keyVals; }; -struct _Relation { - _Relation() : type(unknown){} +struct ExtractorRelation { + ExtractorRelation() : type(unknown){} enum { unknown = 0, ferry, turnRestriction } type; HashTable keyVals; }; -struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { +struct InternalExtractorEdge { + InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { assert(0 <= type); } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -112,15 +112,16 @@ struct _Edge { _Coordinate startCoord; _Coordinate targetCoord; - static _Edge min_value() { - return _Edge(0,0); + static InternalExtractorEdge min_value() { + return InternalExtractorEdge(0,0); } - static _Edge max_value() { - return _Edge((std::numeric_limits::max)(), (std::numeric_limits::max)()); + static InternalExtractorEdge max_value() { + return InternalExtractorEdge((std::numeric_limits::max)(), (std::numeric_limits::max)()); } - }; + + struct _WayIDStartAndEndEdge { unsigned wayID; NodeID firstStart; @@ -177,34 +178,29 @@ struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> { } }; -struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const { +struct CmpEdgeByStartID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.start < b.start; } value_type max_value() { - return _Edge::max_value(); + return InternalExtractorEdge::max_value(); } value_type min_value() { - return _Edge::min_value(); + return InternalExtractorEdge::min_value(); } }; -struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const - { +struct CmpEdgeByTargetID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.target < b.target; } - value_type max_value() - { - return _Edge::max_value(); + value_type max_value() { + return InternalExtractorEdge::max_value(); } - value_type min_value() - { - return _Edge::min_value(); + value_type min_value() { + return InternalExtractorEdge::min_value(); } }; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index d86fbc457..222475db6 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -332,8 +332,8 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { } inline void PBFParser::parseWay(_ThreadData * threadData) { - _Way w; - std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); + ExtractionWay w; + std::vector waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { w.Clear(); const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); @@ -356,7 +356,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { unsigned endi_ways = waysToParse.size(); #pragma omp parallel for schedule ( guided ) for(unsigned i = 0; i < endi_ways; ++i) { - _Way & w = waysToParse[i]; + ExtractionWay & w = waysToParse[i]; /** Pass the unpacked way to the LUA call back **/ try { luabind::call_function( @@ -376,7 +376,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { // } } - BOOST_FOREACH(_Way & w, waysToParse) { + BOOST_FOREACH(ExtractionWay & w, waysToParse) { if(!externalMemory->wayFunction(w)) { std::cerr << "[PBFParser] way not parsed" << std::endl; } diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index ed469272d..d3da02706 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -41,7 +41,7 @@ #include "ExtractorStructs.h" #include "ScriptingEnvironment.h" -class PBFParser : public BaseParser { +class PBFParser : public BaseParser { enum EntityType { TypeNode = 1, diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index b4b6af54e..ca8d9a754 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -65,19 +65,19 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ]; luabind::module(myLuaState) [ - luabind::class_<_Way>("Way") + luabind::class_("Way") .def(luabind::constructor<>()) - .def_readwrite("name", &_Way::name) - .def_readwrite("backward_speed", &_Way::backward_speed) - .def_readwrite("speed", &_Way::speed) - .def_readwrite("type", &_Way::type) - .def_readwrite("access", &_Way::access) - .def_readwrite("roundabout", &_Way::roundabout) - .def_readwrite("is_duration_set", &_Way::isDurationSet) - .def_readwrite("is_access_restricted", &_Way::isAccessRestricted) - .def_readwrite("ignore_in_grid", &_Way::ignoreInGrid) - .def_readwrite("tags", &_Way::keyVals) - .def_readwrite("direction", &_Way::direction) + .def_readwrite("name", &ExtractionWay::name) + .def_readwrite("backward_speed", &ExtractionWay::backward_speed) + .def_readwrite("speed", &ExtractionWay::speed) + .def_readwrite("type", &ExtractionWay::type) + .def_readwrite("access", &ExtractionWay::access) + .def_readwrite("roundabout", &ExtractionWay::roundabout) + .def_readwrite("is_duration_set", &ExtractionWay::isDurationSet) + .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted) + .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) + .def_readwrite("tags", &ExtractionWay::keyVals) + .def_readwrite("direction", &ExtractionWay::direction) .enum_("constants") [ luabind::value("notSure", 0), diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 6449add3f..5faa5a71e 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -100,7 +100,7 @@ bool XMLParser::Parse() { } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - _Way way = _ReadXMLWay( ); + ExtractionWay way = _ReadXMLWay( ); /** Pass the unpacked way to the LUA call back **/ try { @@ -222,8 +222,8 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { return restriction; } -_Way XMLParser::_ReadXMLWay() { - _Way way; +ExtractionWay XMLParser::_ReadXMLWay() { + ExtractionWay way; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index d87c50145..3bc54825d 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -28,7 +28,7 @@ #include "ExtractorCallbacks.h" #include "ScriptingEnvironment.h" -class XMLParser : public BaseParser { +class XMLParser : public BaseParser { public: XMLParser(const char * filename); virtual ~XMLParser(); @@ -39,7 +39,7 @@ public: private: _RawRestrictionContainer _ReadXMLRestriction(); - _Way _ReadXMLWay(); + ExtractionWay _ReadXMLWay(); ImportNode _ReadXMLNode( ); /* Input Reader */ xmlTextReaderPtr inputReader; diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index b22086c39..40bc98a9c 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -101,7 +101,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL short type; NodeID nameID; int length; - bool isRoundabout, ignoreInGrid, isAccessRestricted; + bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; for (EdgeID i=0; i& edgeL in.read((char*)&isRoundabout, sizeof(bool)); in.read((char*)&ignoreInGrid, sizeof(bool)); in.read((char*)&isAccessRestricted, sizeof(bool)); + in.read((char*)&isContraFlow, sizeof(bool)); GUARANTEE(length > 0, "loaded null length edge" ); GUARANTEE(weight > 0, "loaded null weight"); @@ -150,7 +151,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL std::swap(forward, backward); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); edgeList.push_back(inputEdge); } std::sort(edgeList.begin(), edgeList.end()); diff --git a/extractor.cpp b/extractor.cpp index d212a837e..1aa72f83b 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -58,7 +58,6 @@ int main (int argc, char *argv[]) { } omp_set_num_threads(numberOfThreads); - INFO("extracting data from input file " << argv[1]); bool isPBF(false); std::string outputFileName(argv[1]); @@ -93,10 +92,9 @@ int main (int argc, char *argv[]) { StringMap stringMap; ExtractionContainers externalMemory; - stringMap[""] = 0; extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap); - BaseParser * parser; + BaseParser * parser; if(isPBF) { parser = new PBFParser(argv[1]); } else { From 86d7442a5f77c86813c4649b7446b7050d13a8ba Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 12 Jan 2013 19:15:08 +0100 Subject: [PATCH 069/161] support comments in test tables --- features/step_definitions/routing.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 32e6f60e5..17a3251c0 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -46,6 +46,9 @@ When /^I route I should get$/ do |table| if table.headers.include? 'turns' got['turns'] = turns end + if table.headers.include? '#' # comment column + got['#'] = row['#'] # copy value so it always match + end end ok = true From 5339f440bdf251971b69424ab4f987ab26c4b5cf Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 18 Jan 2013 22:10:11 +0100 Subject: [PATCH 070/161] test forward/backward maxspeed (car) --- features/car/maxspeed.feature | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index cc31c6c13..abdb72a9e 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -32,3 +32,26 @@ Feature: Car - Max speed restrictions | from | to | route | time | | a | b | ab | 144s ~10% | | b | c | bc | 144s ~10% | + + @oppposite @todo + Scenario: Car - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | + + And the ways + | nodes | highway | maxspeed:forward | maxspeed:backward | + | ab | primary | | | + | bc | primart | 18 | 9 | + | cd | primart | | 9 | + | de | primart | 9 | | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s | + | b | a | ab | 10s | + | b | c | bc | 20s | + | c | b | bc | 40s | + | c | d | cd | 10s | + | d | c | cd | 20s | + | d | e | de | 20s | + | e | d | de | 10s | From 3595ac08f70ebc9e20dad0edbdf76aee1fe5bf8d Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 18 Jan 2013 22:11:22 +0100 Subject: [PATCH 071/161] fix tag on @opposite test --- features/testbot/opposite.feature | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 9b5df779d..bcc4567d3 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -4,8 +4,7 @@ Feature: Separate settings for forward/backward direction Background: Given the profile "testbot" - @smallest - Scenario: Going against the flow + Scenario: Testbot - Going against the flow Given the node map | a | b | c | d | @@ -16,4 +15,4 @@ Feature: Separate settings for forward/backward direction When I route I should get | from | to | route | distance | time | | a | d | abcd | 300 +- 1m | 30s | - | d | a | abcd | 300 +- 1m | 55s | + | d | a | abcd | 300 +- 1m | 55s | \ No newline at end of file From 4f9c422e2f37e527d8746cce662b2a0b0b235911 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 19 Jan 2013 13:04:58 +0100 Subject: [PATCH 072/161] test maxspeed forward/backward --- features/car/maxspeed.feature | 31 ++------------ features/testbot/maxspeed.feature | 70 +++++++++++++++++++++++++++++++ features/testbot/opposite.feature | 2 +- profiles/testbot.lua | 41 +++++++++++++++--- 4 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 features/testbot/maxspeed.feature diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index abdb72a9e..8e40e95bf 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -10,9 +10,9 @@ Feature: Car - Max speed restrictions | a | b | c | And the ways - | nodes | highway | maxspeed | - | ab | trunk | | - | bc | trunk | 10 | + | nodes | highway | maxspeed | + | ab | trunk | | + | bc | trunk | 10 | When I route I should get | from | to | route | time | @@ -31,27 +31,4 @@ Feature: Car - Max speed restrictions When I route I should get | from | to | route | time | | a | b | ab | 144s ~10% | - | b | c | bc | 144s ~10% | - - @oppposite @todo - Scenario: Car - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | - - And the ways - | nodes | highway | maxspeed:forward | maxspeed:backward | - | ab | primary | | | - | bc | primart | 18 | 9 | - | cd | primart | | 9 | - | de | primart | 9 | | - - When I route I should get - | from | to | route | time | - | a | b | ab | 10s | - | b | a | ab | 10s | - | b | c | bc | 20s | - | c | b | bc | 40s | - | c | d | cd | 10s | - | d | c | cd | 20s | - | d | e | de | 20s | - | e | d | de | 10s | + | b | c | bc | 144s ~10% | diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature new file mode 100644 index 000000000..4f454be70 --- /dev/null +++ b/features/testbot/maxspeed.feature @@ -0,0 +1,70 @@ +@routing @maxspeed @testbot +Feature: Car - Max speed restrictions + + Background: Use specific speeds + Given the profile "testbot" + + Scenario: Testbot - Respect maxspeeds when lower that way type speed + Given the node map + | a | b | c | d | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 24 | + | cd | 18 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 15s +-1 | + | c | b | bc | 15s +-1 | + | c | d | cd | 20s +-1 | + | d | c | cd | 20s +-1 | + + Scenario: Testbot - Ignore maxspeed when higher than way speed + Given the node map + | a | b | c | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 200 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 20s +-1 | + | b | c | bc | 20s +-1 | + + @opposite + Scenario: Testbot - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | f | g | h | + + And the ways + | nodes | maxspeed | maxspeed:forward | maxspeed:backward | + | ab | | | | + | bc | 18 | | | + | cd | | 18 | | + | de | | | 18 | + | ef | 9 | 18 | | + | fg | 9 | | 18 | + | gh | 9 | 24 | 18 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 20s +-1 | + | c | b | bc | 20s +-1 | + | c | d | cd | 20s +-1 | + | d | c | cd | 10s +-1 | + | d | e | de | 10s +-1 | + | e | d | de | 20s +-1 | + | e | f | ef | 20s +-1 | + | f | e | ef | 10s +-1 | + | f | g | fg | 10s +-1 | + | g | f | fg | 20s +-1 | + | g | h | gh | 15s +-1 | + | h | g | gh | 10s +-1 | diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index bcc4567d3..fb73c6649 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,4 +1,4 @@ -@routing @opposite +@routing @testbot @opposite Feature: Separate settings for forward/backward direction Background: diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 341cb6d23..2c13a4e5b 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -23,6 +23,18 @@ ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 +function limit_speed(speed, limits) + -- don't use ipairs(), since it stops at the first nil value + for i=1, #limits do + limit = limits[i] + if limit ~= nil and limit > 0 then + if limit < speed then + return limit -- stop at first speedlimit that's smaller than speed + end + end + end + return speed +end function node_function (node) local traffic_signal = node.tags:Find("highway") @@ -45,6 +57,15 @@ function way_function (way, numberOfNodesInWay) local oneway = way.tags:Find("oneway") local route = way.tags:Find("route") local duration = way.tags:Find("duration") + local maxspeed = tonumber(way.tags:Find ( "maxspeed")) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) + + print('---') + print(name) + print(tostring(maxspeed)) + print(tostring(maxspeed_forward)) + print(tostring(maxspeed_backward)) way.name = name @@ -54,12 +75,20 @@ function way_function (way, numberOfNodesInWay) way.is_duration_set = true else way.speed = speed_profile[highway] or speed_profile['default'] - end - - if(highway == "river") then - local temp_speed = way.speed; - way.speed = temp_speed*3/2 - way.backward_speed = temp_speed*2/3 + + if highway == "river" then + local temp_speed = way.speed; + way.speed = temp_speed*3/2 + way.backward_speed = temp_speed*2/3 + else + way.backward_speed = way.speed + end + + way.speed = limit_speed( way.speed, {maxspeed_forward, maxspeed} ) + way.backward_speed = limit_speed( way.backward_speed, {maxspeed_backward, maxspeed} ) + + -- print( 'limit forw: ' .. tostring(way.speed)) + -- print( 'limit back: ' .. tostring(way.backward_speed)) end if oneway == "no" or oneway == "0" or oneway == "false" then From aae0547cca9f1993ee6cadb6c2869c632a543b81 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 19 Jan 2013 16:00:36 +0100 Subject: [PATCH 073/161] better testbot maxspeed handling, fix test --- features/testbot/maxspeed.feature | 6 ++++-- profiles/testbot.lua | 22 +++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature index 4f454be70..1d40233a5 100644 --- a/features/testbot/maxspeed.feature +++ b/features/testbot/maxspeed.feature @@ -34,8 +34,10 @@ Feature: Car - Max speed restrictions When I route I should get | from | to | route | time | - | a | b | ab | 20s +-1 | - | b | c | bc | 20s +-1 | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 10s +-1 | + | c | b | bc | 10s +-1 | @opposite Scenario: Testbot - Forward/backward maxspeed diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 2c13a4e5b..82489850a 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -74,21 +74,25 @@ function way_function (way, numberOfNodesInWay) way.speed = math.max( 1, parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ) way.is_duration_set = true else - way.speed = speed_profile[highway] or speed_profile['default'] + local speed_forw = speed_profile[highway] or speed_profile['default'] + local speed_back = speed_forw if highway == "river" then local temp_speed = way.speed; - way.speed = temp_speed*3/2 - way.backward_speed = temp_speed*2/3 - else - way.backward_speed = way.speed + speed_forw = temp_speed*3/2 + speed_back = temp_speed*2/3 end + + speed_forw = limit_speed( speed_forw, {maxspeed_forward, maxspeed} ) + speed_back = limit_speed( speed_back, {maxspeed_backward, maxspeed} ) - way.speed = limit_speed( way.speed, {maxspeed_forward, maxspeed} ) - way.backward_speed = limit_speed( way.backward_speed, {maxspeed_backward, maxspeed} ) + way.speed = speed_forw + if speed_back ~= way_forw then + way.backward_speed = speed_back + end - -- print( 'limit forw: ' .. tostring(way.speed)) - -- print( 'limit back: ' .. tostring(way.backward_speed)) + -- print( 'speed forw: ' .. tostring(way.speed)) + -- print( 'speed back: ' .. tostring(way.backward_speed)) end if oneway == "no" or oneway == "0" or oneway == "false" then From 6317b080907d053810e26189e8a72d84b2251339 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:03:51 +0100 Subject: [PATCH 074/161] Fixing test cases to check for different speeds in opposite direction --- features/testbot/maxspeed.feature | 6 ++-- features/testbot/opposite.feature | 2 +- profiles/testbot.lua | 47 +++++++++++++------------------ 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature index 1d40233a5..bd9a56987 100644 --- a/features/testbot/maxspeed.feature +++ b/features/testbot/maxspeed.feature @@ -65,8 +65,8 @@ Feature: Car - Max speed restrictions | d | e | de | 10s +-1 | | e | d | de | 20s +-1 | | e | f | ef | 20s +-1 | - | f | e | ef | 10s +-1 | - | f | g | fg | 10s +-1 | + | f | e | ef | 40s +-1 | + | f | g | fg | 40s +-1 | | g | f | fg | 20s +-1 | | g | h | gh | 15s +-1 | - | h | g | gh | 10s +-1 | + | h | g | gh | 20s +-1 | diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index fb73c6649..c242c97b1 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -15,4 +15,4 @@ Feature: Separate settings for forward/backward direction When I route I should get | from | to | route | distance | time | | a | d | abcd | 300 +- 1m | 30s | - | d | a | abcd | 300 +- 1m | 55s | \ No newline at end of file + | d | a | abcd | 300 +- 1m | 68s | \ No newline at end of file diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 82489850a..ccd0d7048 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -23,19 +23,6 @@ ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 -function limit_speed(speed, limits) - -- don't use ipairs(), since it stops at the first nil value - for i=1, #limits do - limit = limits[i] - if limit ~= nil and limit > 0 then - if limit < speed then - return limit -- stop at first speedlimit that's smaller than speed - end - end - end - return speed -end - function node_function (node) local traffic_signal = node.tags:Find("highway") @@ -61,12 +48,6 @@ function way_function (way, numberOfNodesInWay) local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) - print('---') - print(name) - print(tostring(maxspeed)) - print(tostring(maxspeed_forward)) - print(tostring(maxspeed_backward)) - way.name = name if route ~= nil and durationIsValid(duration) then @@ -78,21 +59,31 @@ function way_function (way, numberOfNodesInWay) local speed_back = speed_forw if highway == "river" then - local temp_speed = way.speed; - speed_forw = temp_speed*3/2 - speed_back = temp_speed*2/3 - end + local temp_speed = speed_forw; + speed_forw = temp_speed*1.5 + speed_back = temp_speed/1.5 + end - speed_forw = limit_speed( speed_forw, {maxspeed_forward, maxspeed} ) - speed_back = limit_speed( speed_back, {maxspeed_backward, maxspeed} ) + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + speed_forw = maxspeed_forward + else + if maxspeed ~= nil and maxspeed > 0 and speed_forw > maxspeed then + speed_forw = maxspeed + end + end + + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + speed_back = maxspeed_backward + else + if maxspeed ~=nil and maxspeed > 0 and speed_back > maxspeed then + speed_back = maxspeed + end + end way.speed = speed_forw if speed_back ~= way_forw then way.backward_speed = speed_back end - - -- print( 'speed forw: ' .. tostring(way.speed)) - -- print( 'speed back: ' .. tostring(way.backward_speed)) end if oneway == "no" or oneway == "0" or oneway == "false" then From 91dc1b66392d3d7a06770867ab98bc3835a59106 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:16:32 +0100 Subject: [PATCH 075/161] Adding curly braces where appropriate --- Contractor/Contractor.h | 10 ++++++---- Contractor/EdgeBasedGraphFactory.cpp | 13 +++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 495b13147..b9059ca62 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -157,11 +157,13 @@ public: forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max(); //remove parallel edges while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) { - if ( edges[i].data.forward ) + if ( edges[i].data.forward) { forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance ); - if ( edges[i].data.backward ) + } + if ( edges[i].data.backward) { backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance ); - i++; + } + ++i; } //merge edges (s,t) and (t,s) into bidirectional edge if ( forwardEdge.data.distance == backwardEdge.data.distance ) { @@ -242,7 +244,7 @@ public: nodePriority[x] = _Evaluate( data, &nodeData[x], x ); } } - std::cout << "ok" << std::endl << "preprocessing ..." << std::flush; + std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush; bool flushedContractor = false; while ( numberOfContractedNodes < numberOfNodes ) { diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index b6bc1e437..5aaacb859 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -67,9 +67,9 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectorisForward(); edge.data.backward = i->isBackward(); } - if(edge.source == edge.target) - continue; - + if(edge.source == edge.target) { + continue; + } edge.data.distance = (std::max)((int)i->weight(), 1 ); assert( edge.data.distance > 0 ); edge.data.shortcut = false; @@ -118,7 +118,7 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource); if (restrIter != _restrictionMap.end()) { unsigned index = restrIter->second; - BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) { + BOOST_FOREACH(const RestrictionSource & restrictionTarget, _restrictionBucketVector.at(index)) { if(restrictionTarget.second) { return restrictionTarget.first; } @@ -250,6 +250,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) { ++nodeBasedEdgeCounter; _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1); + bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end()); //EdgeWeight heightPenalty = ComputeHeightPenalty(u, v); NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v); for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) { @@ -259,7 +260,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { ++numberOfSkippedTurns; continue; } - bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end()); + if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) { continue; } @@ -302,7 +303,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { originalEdgeData.clear(); } ++numberOfOriginalEdges; - ++nodeBasedEdgeCounter; edgeBasedEdges.push_back(newEdge); } else { ++numberOfSkippedTurns; @@ -327,6 +327,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { // std::vector(edgeBasedNodes).swap(edgeBasedNodes); // INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity()); INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges"); + INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges"); // INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter)); INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions."); INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); From 6373b3e49c1a4f4e84ed8bcd8da59c8cf36c7829 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:18:54 +0100 Subject: [PATCH 076/161] Adding first implementation of back() reference function --- DataStructures/DeallocatingVector.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/DataStructures/DeallocatingVector.h b/DataStructures/DeallocatingVector.h index 89502f7d4..d3c19d170 100644 --- a/DataStructures/DeallocatingVector.h +++ b/DataStructures/DeallocatingVector.h @@ -302,6 +302,18 @@ public: size_t _index = index % bucketSizeC; return (mBucketList[_bucket][_index]); } + + inline ElementT & back() { + size_t _bucket = mCurrentSize / bucketSizeC; + size_t _index = mCurrentSize % bucketSizeC; + return (mBucketList[_bucket][_index]); + } + + const inline ElementT & back() const { + size_t _bucket = mCurrentSize / bucketSizeC; + size_t _index = mCurrentSize % bucketSizeC; + return (mBucketList[_bucket][_index]); + } }; #endif /* DEALLOCATINGVECTOR_H_ */ From 6948d56e5dc82c4bf9f51ee09868b904e932f3ac Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:19:48 +0100 Subject: [PATCH 077/161] Fixing edge array sentinel at position n+1 --- DataStructures/DynamicGraph.h | 1 + 1 file changed, 1 insertion(+) diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h index c2a54059d..64bfa6087 100644 --- a/DataStructures/DynamicGraph.h +++ b/DataStructures/DynamicGraph.h @@ -72,6 +72,7 @@ class DynamicGraph { m_nodes[node].edges = edge - lastEdge; position += m_nodes[node].edges; } + m_nodes.back().firstEdge = position; m_edges.reserve( position * 1.1 ); m_edges.resize( position ); edge = 0; From 01a6e3c6192b3cd81c406e357e3ec7cf8b18a6ca Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:21:42 +0100 Subject: [PATCH 078/161] Fixed the computation of reverse edge weight --- DataStructures/NNGrid.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 92a6594e6..8c0747448 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -218,7 +218,7 @@ public: // } // INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location); - double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0); + const double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0); resultNode.location.lat = round(100000.*(y2lat(static_cast(resultNode.location.lat)/100000.))); // INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)); //Hack to fix rounding errors and wandering via nodes. @@ -229,12 +229,13 @@ public: resultNode.weight1 *= ratio; if(INT_MAX != resultNode.weight2) { - resultNode.weight2 -= resultNode.weight1; + resultNode.weight2 *= (1.-ratio); } resultNode.ratio = ratio; -// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio); // INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord); -// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--"); +// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no")); +// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio); + // INFO("distance to input coordinate: " << ApproximateDistance(location, resultNode.location) << "\n--"); // double time2 = get_timestamp(); // INFO("NN-Lookup in " << 1000*(time2-time1) << "ms"); return foundNode; From f7c6b9a0f70037d5e491ff83d30dde1e45c2aaae Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 14:23:29 +0100 Subject: [PATCH 079/161] Fixed direction flag on split edges --- Extractor/ExtractorCallbacks.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 6a5ee1c14..332be2450 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -82,18 +82,17 @@ bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { if ( parsed_way.direction == ExtractionWay::opposite ){ std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); - } - - if( parsed_way.backward_speed > 0 && parsed_way.direction == ExtractionWay::bidirectional) { parsed_way.direction = ExtractionWay::oneway; } + bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n+1], parsed_way.type, - (ExtractionWay::bidirectional == parsed_way.direction && parsed_way.backward_speed > 0 ? ExtractionWay::oneway : parsed_way.direction), + (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), parsed_way.speed, parsed_way.nameID, parsed_way.roundabout, @@ -109,7 +108,7 @@ bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { //The following information is needed to identify start and end segments of restrictions externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); - if ( parsed_way.backward_speed > 0 ) { //Only true if the way should be split + if ( split_bidirectional_edge) { //Only true if the way should be split std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( From ccdc6f1a632838708458d791d94449cc76d900c9 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:00:06 +0100 Subject: [PATCH 080/161] Removing dead code --- createHierarchy.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 87e9105c4..59fdfa63b 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -97,7 +97,6 @@ int main (int argc, char *argv[]) { std::string graphOut(argv[1]); graphOut += ".hsgr"; std::string ramIndexOut(argv[1]); ramIndexOut += ".ramIndex"; std::string fileIndexOut(argv[1]); fileIndexOut += ".fileIndex"; - std::string levelInfoOut(argv[1]); levelInfoOut += ".levels"; /*** Setup Scripting Environment ***/ if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) { From a92950d2345a30c0a53ff3c985d33d968a802c99 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:01:37 +0100 Subject: [PATCH 081/161] Fixes how durations are parsed --- profiles/bicycle.lua | 3 +-- profiles/testbot.lua | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 6038126ee..3c14dc250 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -162,8 +162,7 @@ function way_function (way, numberOfNodesInWay) way.direction = Way.bidirectional way.ignore_in_grid = true if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ) - way.is_duration_set = true + way.duration = math.max( 1, parseDuration(duration) ) else way.speed = route_speeds[route] end diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 3eb1ff339..9c7b103ac 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -49,9 +49,7 @@ function way_function (way, numberOfNodesInWay) way.name = name if route ~= nil and durationIsValid(duration) then - way.ignore_in_grid = true - way.speed = math.max( 1, parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ) - way.is_duration_set = true + way.duration = math.max( 1, parseDuration(duration) ) else way.speed = speed_profile[highway] or speed_profile['default'] end From 86f4aebeade45eaa352e0c53acafc312d55d4a8e Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:03:04 +0100 Subject: [PATCH 082/161] Fixes test to expect time in minutes not seconds --- features/testbot/duration.feature | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature index 67bbe559d..bdf6344bb 100644 --- a/features/testbot/duration.feature +++ b/features/testbot/duration.feature @@ -18,8 +18,8 @@ Feature: Durations | de | primary | 10:00 | When I route I should get - | from | to | route | distance | time | - | a | b | ab | 100m +-1 | 1s +-1 | - | b | c | bc | 200m +-1 | 10s +-1 | - | c | d | cd | 300m +-1 | 60s +-1 | - | d | e | de | 144m +-1 | 600s +-1 | + | from | to | route | distance | time | + | a | b | ab | 100m +-1 | 60s +-1 | + | b | c | bc | 200m +-1 | 600s +-1 | + | c | d | cd | 300m +-1 | 3600s +-1 | + | d | e | de | 144m +-2 | 36000s +-1 | From 59481dd762797f396129b528d3541af449c7bf89 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:05:27 +0100 Subject: [PATCH 083/161] Adding duration member to way --- Extractor/ExtractorStructs.h | 4 ++-- Extractor/ScriptingEnvironment.cpp | 2 +- Extractor/XMLParser.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe5dd1b40..5ea22cbd9 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -52,10 +52,10 @@ struct _Way { keyVals.EraseAll(); direction = _Way::notSure; speed = -1; + duration = -1; type = -1; access = true; roundabout = false; - isDurationSet = false; isAccessRestricted = false; ignoreInGrid = false; } @@ -67,10 +67,10 @@ struct _Way { unsigned nameID; std::string name; double speed; + double duration; short type; bool access; bool roundabout; - bool isDurationSet; bool isAccessRestricted; bool ignoreInGrid; std::vector< NodeID > path; diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index c2f42d79d..330eac6af 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -69,10 +69,10 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { .def(luabind::constructor<>()) .def_readwrite("name", &_Way::name) .def_readwrite("speed", &_Way::speed) + .def_readwrite("duration", &_Way::duration) .def_readwrite("type", &_Way::type) .def_readwrite("access", &_Way::access) .def_readwrite("roundabout", &_Way::roundabout) - .def_readwrite("is_duration_set", &_Way::isDurationSet) .def_readwrite("is_access_restricted", &_Way::isAccessRestricted) .def_readwrite("ignore_in_grid", &_Way::ignoreInGrid) .def_readwrite("tags", &_Way::keyVals) diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 6449add3f..6b2c8a97d 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -139,7 +139,6 @@ bool XMLParser::Parse() { _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { _RawRestrictionContainer restriction; std::string exception_of_restriction_tag; - bool restriction_is_excepted = false; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { From 03de87c2134b388adfb0ef5d4a9d2795095a2a64 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:06:23 +0100 Subject: [PATCH 084/161] Parsing duration when present --- Extractor/ExtractorCallbacks.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 3db1d8d8b..956a9fee4 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -67,8 +67,7 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { bool ExtractorCallbacks::wayFunction(_Way &w) { /*** Store name of way and split it into edge segments ***/ - if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile - + if ( 0 < w.speed > 0 || 0 < w.duration ) { //Only true if the way is specified by the speed profile //Get the unique identifier for the street name const StringMap::const_iterator strit = stringMap->find(w.name); if(strit == stringMap->end()) { @@ -79,6 +78,11 @@ bool ExtractorCallbacks::wayFunction(_Way &w) { w.nameID = strit->second; } + if(w.duration > 0) { + //TODO: iterate all way segments and set duration corresponding to the length of each segment + w.speed = w.duration/(w.path.size()-1); + } + if(fabs(-1. - w.speed) < FLT_EPSILON){ WARN("found way with bogus speed, id: " << w.id); return true; @@ -93,7 +97,7 @@ bool ExtractorCallbacks::wayFunction(_Way &w) { } for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted)); + externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, (w.duration > 0), w.isAccessRestricted)); externalMemory->usedNodeIDs.push_back(w.path[n]); } externalMemory->usedNodeIDs.push_back(w.path.back()); From 0ffa973ec63f1372531d0483d40fc404f89a8ed7 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 27 Jan 2013 23:08:45 +0100 Subject: [PATCH 085/161] Exit gracefully when data is empty --- DataStructures/NNGrid.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 92a6594e6..4c156ea61 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -108,6 +108,9 @@ public: int tlon = edge.lon2; AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) ); } + if( 0 == entries.size() ) { + ERR("No viable edges for nearest neighbor index. Aborting"); + } double timestamp = get_timestamp(); //create index file on disk, old one is over written indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc); From 061d78c68163d4655ef9c5d92b66d4bc1cdbc3e1 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 28 Jan 2013 08:30:34 +0100 Subject: [PATCH 086/161] test partial duration of ways --- features/testbot/duration.feature | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature index bdf6344bb..3d6735cc5 100644 --- a/features/testbot/duration.feature +++ b/features/testbot/duration.feature @@ -23,3 +23,17 @@ Feature: Durations | b | c | bc | 200m +-1 | 600s +-1 | | c | d | cd | 300m +-1 | 3600s +-1 | | d | e | de | 144m +-2 | 36000s +-1 | + + Scenario: Partial duration of ways + Given the node map + | a | b | | c | + + And the ways + | nodes | highway | duration | + | abc | primary | 0:01 | + + When I route I should get + | from | to | route | distance | time | + | a | c | abc | 300m +-1 | 60s +-1 | + | a | b | ab | 100m +-1 | 20s +-1 | + | b | c | bc | 200m +-1 | 40s +-1 | From cb2fcf4f520f22d96e1dfbcb1230bb23b053f849 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 28 Jan 2013 09:39:18 +0100 Subject: [PATCH 087/161] add @todo tag to partial way duration test --- features/testbot/duration.feature | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature index 3d6735cc5..d22f28c4b 100644 --- a/features/testbot/duration.feature +++ b/features/testbot/duration.feature @@ -23,7 +23,8 @@ Feature: Durations | b | c | bc | 200m +-1 | 600s +-1 | | c | d | cd | 300m +-1 | 3600s +-1 | | d | e | de | 144m +-2 | 36000s +-1 | - + + @todo Scenario: Partial duration of ways Given the node map | a | b | | c | From bcf4af4a2f9041a9679e9a1bee94ece09886303a Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 29 Jan 2013 10:11:04 +0100 Subject: [PATCH 088/161] Duration tag now handles 'hh:mm', 'mm' as well as 'hh:mm:ss' --- Extractor/ExtractionHelperFunctions.h | 29 +++++++++++++++++++-------- features/testbot/duration.feature | 8 +++++--- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Extractor/ExtractionHelperFunctions.h b/Extractor/ExtractionHelperFunctions.h index 08a1e14ef..6771939a9 100644 --- a/Extractor/ExtractionHelperFunctions.h +++ b/Extractor/ExtractionHelperFunctions.h @@ -28,12 +28,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include + #include "../Util/StringUtil.h" +namespace qi = boost::spirit::qi; + //TODO: Move into LUA inline bool durationIsValid(const std::string &s) { - boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); + boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); std::vector< std::string > result; boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ; @@ -42,17 +45,28 @@ inline bool durationIsValid(const std::string &s) { } inline unsigned parseDuration(const std::string &s) { - int hours = 0; - int minutes = 0; - boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); + unsigned hours = 0; + unsigned minutes = 0; + unsigned seconds = 0; + boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); std::vector< std::string > result; boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ; bool matched = regex_match(s, e); if(matched) { - hours = (result.size()== 2) ? stringToInt(result[0]) : 0; - minutes = (result.size()== 2) ? stringToInt(result[1]) : stringToInt(result[0]); - return 600*(hours*60+minutes); + if(1 == result.size()) { + minutes = stringToInt(result[0]); + } + if(2 == result.size()) { + minutes = stringToInt(result[1]); + hours = stringToInt(result[0]); + } + if(3 == result.size()) { + seconds = stringToInt(result[2]); + minutes = stringToInt(result[1]); + hours = stringToInt(result[0]); + } + return 10*(3600*hours+60*minutes+seconds); } return UINT_MAX; } @@ -66,5 +80,4 @@ inline int parseMaxspeed(std::string input) { //call-by-value on purpose. return n; } - #endif /* EXTRACTIONHELPERFUNCTIONS_H_ */ diff --git a/features/testbot/duration.feature b/features/testbot/duration.feature index d22f28c4b..ab6571ce5 100644 --- a/features/testbot/duration.feature +++ b/features/testbot/duration.feature @@ -6,9 +6,9 @@ Feature: Durations Scenario: Duration of ways Given the node map - | a | b | | | | - | | | | e | | - | | c | | | d | + | a | b | | | | f | + | | | | e | | | + | | c | | | d | | And the ways | nodes | highway | duration | @@ -16,6 +16,7 @@ Feature: Durations | bc | primary | 0:10 | | cd | primary | 1:00 | | de | primary | 10:00 | + | ef | primary | 01:02:03 | When I route I should get | from | to | route | distance | time | @@ -23,6 +24,7 @@ Feature: Durations | b | c | bc | 200m +-1 | 600s +-1 | | c | d | cd | 300m +-1 | 3600s +-1 | | d | e | de | 144m +-2 | 36000s +-1 | + | e | f | ef | 224m +-2 | 3723s +-1 | @todo Scenario: Partial duration of ways From e0c211085c57966e01767d21cc2f459bf60434ff Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 29 Jan 2013 17:36:28 +0100 Subject: [PATCH 089/161] Handle route=shuttle_train again --- features/car/shuttle_train.feature | 31 ++++++++++++++++++++++++++++++ profiles/car.lua | 1 + 2 files changed, 32 insertions(+) create mode 100644 features/car/shuttle_train.feature diff --git a/features/car/shuttle_train.feature b/features/car/shuttle_train.feature new file mode 100644 index 000000000..ed2187c27 --- /dev/null +++ b/features/car/shuttle_train.feature @@ -0,0 +1,31 @@ +@routing @car @shuttle_train +Feature: Car - Handle ferryshuttle train routes + + Background: + Given the profile "car" + + Scenario: Car - Use a ferry route + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | route | bicycle | + | abc | primary | | | + | cde | | shuttle_train | yes | + | ef | primary | | | + | fg | | ferry_man | | + + When I route I should get + | from | to | route | + | a | g | abc,cde,ef | + | b | f | abc,cde,ef | + | e | c | cde | + | e | b | cde,abc | + | e | a | cde,abc | + | c | e | cde | + | c | f | cde,ef | + | f | g | | + + diff --git a/profiles/car.lua b/profiles/car.lua index c078647f6..0effd8138 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -28,6 +28,7 @@ speed_profile = { ["service"] = 15, -- ["track"] = 5, ["ferry"] = 5, + ["shuttle_train"] = 10, ["default"] = 50 } From 9db884f371f915ac2bbc44689ac280a4c4b3b0ed Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 30 Jan 2013 13:46:20 +0100 Subject: [PATCH 090/161] Fixing duration parsing --- profile.lua | 209 ----------------------------------------------- profiles/car.lua | 5 +- 2 files changed, 2 insertions(+), 212 deletions(-) delete mode 100644 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 100644 index c078647f6..000000000 --- a/profile.lua +++ /dev/null @@ -1,209 +0,0 @@ --- Begin of globals -require("lib/access") - -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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 } -access_tag_restricted = { ["destination"] = true, ["delivery"] = true } -access_tags = { "motorcar", "motor_vehicle", "vehicle" } -access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } -service_tag_restricted = { ["parking_aisle"] = true } -ignore_in_grid = { ["ferry"] = true } -restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } - -speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, --- ["track"] = 5, - ["ferry"] = 5, - ["default"] = 50 -} - -take_minimum_of_speeds = false -obey_oneway = true -obey_bollards = true -use_restrictions = true -ignore_areas = true -- future feature -traffic_signal_penalty = 2 -u_turn_penalty = 20 - --- End of globals - -function get_exceptions(vector) - for i,v in ipairs(restriction_exception_tags) do - vector:Add(v) - end -end - -local function parse_maxspeed(source) - if source == nil then - return 0 - end - local n = tonumber(source:match("%d*")) - if n == nil then - n = 0 - end - if string.match(source, "mph") or string.match(source, "mp/h") then - n = (n*1609)/1000; - end - return math.abs(n) -end - -function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; - end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end - end - return 1 -end - - -function way_function (way, numberOfNodesInWay) - - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name --- else --- way.name = highway -- if no name exists, use way type - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) - then - if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); - way.is_duration_set = true - end - way.direction = Way.bidirectional - if speed_profile[route] ~= nil then - highway = route; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) - end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end - - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end - - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel - - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 - return 1 -end - --- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT - -function node_vector_function(vector) - for v in vector.nodes do - node_function(v) - end -end diff --git a/profiles/car.lua b/profiles/car.lua index 0effd8138..5d9b86463 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -139,14 +139,13 @@ function way_function (way, numberOfNodesInWay) if (speed_profile[route] ~= nil and speed_profile[route] > 0) then if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); - way.is_duration_set = true + way.duration = math.max( parseDuration(duration), 1 ); end way.direction = Way.bidirectional if speed_profile[route] ~= nil then highway = route; end - if not way.is_duration_set then + if not way.duration > 0 then way.speed = speed_profile[highway] end end From 9ecfed4e56d4051efced619eab4f532094a517da Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 30 Jan 2013 13:47:24 +0100 Subject: [PATCH 091/161] linking to car profile --- profile.lua | 1 + 1 file changed, 1 insertion(+) create mode 120000 profile.lua diff --git a/profile.lua b/profile.lua new file mode 120000 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file From adf0c726ef666c2dbc70f867ef56b806ab9b38f2 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 30 Jan 2013 14:03:21 +0100 Subject: [PATCH 092/161] Further changes to duration handling --- profiles/car.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/profiles/car.lua b/profiles/car.lua index 5d9b86463..1a383d1fa 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -136,8 +136,7 @@ function way_function (way, numberOfNodesInWay) end -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) - then + if (speed_profile[route] ~= nil and speed_profile[route] > 0) then if durationIsValid(duration) then way.duration = math.max( parseDuration(duration), 1 ); end @@ -145,7 +144,7 @@ function way_function (way, numberOfNodesInWay) if speed_profile[route] ~= nil then highway = route; end - if not way.duration > 0 then + if tonumber(way.duration) < 0 then way.speed = speed_profile[highway] end end @@ -165,6 +164,11 @@ function way_function (way, numberOfNodesInWay) end way.speed = math.min(speed_profile["default"], maxspeed) end + + if durationIsValid(duration) then + way.duration = math.max( parseDuration(duration), 1 ); + end + -- Set access restriction flag if access is allowed under certain restrictions only if access ~= "" and access_tag_restricted[access] then From 78c92be14ba2b376ec254f3246f494d4b265fbad Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 1 Feb 2013 13:21:12 +0100 Subject: [PATCH 093/161] Fixes issue #577, syntax error in JSONP response --- Plugins/LocatePlugin.h | 6 +++--- Plugins/NearestPlugin.h | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Plugins/LocatePlugin.h b/Plugins/LocatePlugin.h index 39d83b345..c26e75fb6 100644 --- a/Plugins/LocatePlugin.h +++ b/Plugins/LocatePlugin.h @@ -52,12 +52,12 @@ public: //query to helpdesk _Coordinate result; - std::string JSONParameter, tmp; + std::string tmp; //json // JSONParameter = routeParameters.options.Find("jsonp"); if("" != routeParameters.jsonpParameter) { - reply.content += JSONParameter; + reply.content += routeParameters.jsonpParameter; reply.content += "("; } reply.status = http::Reply::ok; @@ -82,7 +82,7 @@ public: reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\""; reply.content += ("}"); reply.headers.resize(3); - if("" != JSONParameter) { + if("" != routeParameters.jsonpParameter) { reply.content += ")"; reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h index 53dc1bd51..c10230f6c 100644 --- a/Plugins/NearestPlugin.h +++ b/Plugins/NearestPlugin.h @@ -60,7 +60,6 @@ public: nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel); std::string tmp; - std::string JSONParameter; //json if("" != routeParameters.jsonpParameter) { @@ -93,7 +92,7 @@ public: reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\""; reply.content += ("}"); reply.headers.resize(3); - if("" != JSONParameter) { + if("" != routeParameters.jsonpParameter) { reply.content += ")"; reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; From 59ca59d431bc6f4eaf72a75ff6c11ae49a912b81 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 13:19:23 +0100 Subject: [PATCH 094/161] Using unordered_set where it suffices --- Contractor/EdgeBasedGraphFactory.cpp | 12 +++--------- Contractor/EdgeBasedGraphFactory.h | 7 ++++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 4126cff01..e484a25e6 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -44,18 +44,12 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector edges; - // edges.reserve( 2 * inputEdges.size() ); + _NodeBasedEdge edge; for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) { - - _NodeBasedEdge edge; if(!i->isForward()) { edge.source = i->target(); edge.target = i->source(); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 0b909b264..12c6c198b 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -35,7 +35,8 @@ #include #include #include - +#include +#include #include "../typedefs.h" #include "../DataStructures/DeallocatingVector.h" @@ -103,8 +104,8 @@ public: } speedProfile; private: boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph; - boost::unordered_map _barrierNodes; - boost::unordered_map _trafficLights; + boost::unordered_set _barrierNodes; + boost::unordered_set _trafficLights; typedef std::pair RestrictionSource; typedef std::pair RestrictionTarget; From b3d517943a122e132052436f6c6892c7b99d838f Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 13:07:30 +0100 Subject: [PATCH 095/161] fuzzy ranges on routability tables, value shortcuts --- features/step_definitions/data.rb | 6 ++++++ features/step_definitions/routability.rb | 7 +++++-- features/step_definitions/routing.rb | 26 +++--------------------- features/support/data.rb | 11 ++++++++-- features/support/fuzzy.rb | 26 ++++++++++++++++++++++++ features/support/shortcuts.rb | 3 +++ 6 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 features/support/fuzzy.rb create mode 100644 features/support/shortcuts.rb diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb index c2cf35c3b..c16adaacb 100644 --- a/features/step_definitions/data.rb +++ b/features/step_definitions/data.rb @@ -6,6 +6,12 @@ Given /^a grid size of (\d+) meters$/ do |meters| set_grid_size meters end +Given /^the shortcuts$/ do |table| + table.hashes.each do |row| + shortcuts_hash[ row['key'] ] = row['value'] + end +end + Given /^the node map$/ do |table| table.raw.each_with_index do |row,ri| row.each_with_index do |name,ci| diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index d949d01b9..0af027a98 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -16,18 +16,21 @@ Then /^routability should be$/ do |table| elsif direction == 'backw' || direction == 'bothw' response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}") end + want = shortcuts_hash[row[direction]] || row[direction] #expand shortcuts got[direction] = route_status response json = JSON.parse(response.body) if got[direction].empty? == false route = way_list json['route_instructions'] if route != "w#{i}" got[direction] = "testing w#{i}, but got #{route}!?" - elsif row[direction] =~ /\d+s/ + elsif want =~ /^\d+s/ time = json['route_summary']['total_time'] got[direction] = "#{time}s" end end - if got[direction] != row[direction] + if FuzzyMatch.match got[direction], want + got[direction] = row[direction] + else attempts << { :attempt => direction, :query => @query, :response => response } end end diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 17a3251c0..175b7e20c 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -53,30 +53,10 @@ When /^I route I should get$/ do |table| ok = true row.keys.each do |key| - if row[key].match /(.*)\s+~(.+)%$/ #percentage range: 100 ~5% - margin = 1 - $2.to_f*0.01 - from = $1.to_f*margin - to = $1.to_f/margin - if got[key].to_f >= from && got[key].to_f <= to - got[key] = row[key] - else - ok = false - end - elsif row[key].match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5 - margin = $2.to_f - from = $1.to_f-margin - to = $1.to_f+margin - if got[key].to_f >= from && got[key].to_f <= to - got[key] = row[key] - else - ok = false - end - elsif row[key] =~ /^\/(.*)\/$/ #regex: /a,b,.*/ - if got[key] =~ /#{$1}/ - got[key] = row[key] - end + if FuzzyMatch.match got[key], row[key] + got[key] = row[key] else - ok = row[key] == got[key] + ok = false end end diff --git a/features/support/data.rb b/features/support/data.rb index f83bbd223..227a962fc 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -71,8 +71,15 @@ def build_ways_from_table table way << node5 tags = row.dup - tags.delete 'forw' - tags.delete 'backw' + + # remove tags that describe expected test result + tags.reject! do |k,v| + k =~ /^forw\b/ || + k =~ /^backw\b/ || + k =~ /^bothw\b/ + end + + ##remove empty tags tags.reject! { |k,v| v=='' } # sort tag keys in the form of 'node/....' diff --git a/features/support/fuzzy.rb b/features/support/fuzzy.rb new file mode 100644 index 000000000..2758c1f82 --- /dev/null +++ b/features/support/fuzzy.rb @@ -0,0 +1,26 @@ + +class FuzzyMatch + + def self.match got, want + if got == want + return true + elsif want.match /(.*)\s+~(.+)%$/ #percentage range: 100 ~5% + margin = 1 - $2.to_f*0.01 + from = $1.to_f*margin + to = $1.to_f/margin + return got.to_f >= from && got.to_f <= to + elsif want.match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5 + margin = $2.to_f + from = $1.to_f-margin + to = $1.to_f+margin + return got.to_f >= from && got.to_f <= to + elsif want =~ /^\/(.*)\/$/ #regex: /a,b,.*/ + return got =~ /#{$1}/ + else + return false + end + end + +end + + diff --git a/features/support/shortcuts.rb b/features/support/shortcuts.rb new file mode 100644 index 000000000..20bc3c0fe --- /dev/null +++ b/features/support/shortcuts.rb @@ -0,0 +1,3 @@ +def shortcuts_hash + @shortcuts_hash ||= {} +end From dd5d520b5383191f172ba808ce1b503ca8d0146a Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 13:08:11 +0100 Subject: [PATCH 096/161] update profile and tests for pushing of bikes --- features/bicycle/access.feature | 167 ++++++++++++++------------ features/bicycle/access_node.feature | 64 ++++++++++ features/bicycle/cycleway.feature | 20 +-- features/bicycle/oneway.feature | 143 +++++++++++----------- features/bicycle/pushing.feature | 72 +++++++++++ features/bicycle/restrictions.feature | 120 +++++++++--------- features/bicycle/way.feature | 60 ++++----- features/car/permissive.feature | 0 profiles/bicycle.lua | 152 +++++++++++++---------- 9 files changed, 494 insertions(+), 304 deletions(-) create mode 100644 features/bicycle/access_node.feature create mode 100644 features/bicycle/pushing.feature create mode 100644 features/car/permissive.feature diff --git a/features/bicycle/access.feature b/features/bicycle/access.feature index 149a2743c..cb1fc0d0b 100644 --- a/features/bicycle/access.feature +++ b/features/bicycle/access.feature @@ -1,5 +1,5 @@ @routing @bicycle @access -Feature: Bike - Restricted access +Feature: Bike - Access tags on ways Reference: http://wiki.openstreetmap.org/wiki/Key:access Background: @@ -7,37 +7,95 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access Scenario: Bike - Access tag hierachy on ways Then routability should be - | access | vehicle | 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 | | + | highway | access | vehicle | 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 | | + | runway | | | | | + | runway | yes | | | x | + | runway | no | | | | + | runway | | yes | | x | + | runway | | no | | | + | runway | no | yes | | x | + | runway | yes | no | | | + | runway | | | yes | x | + | runway | | | no | | + | runway | no | | yes | x | + | runway | yes | | no | | + | runway | | no | yes | x | + | runway | | yes | no | | - 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 | | + @todo + Scenario: Bike - Access tag in forward direction + Then routability should be + | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw | + | | | | | 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 | | | + | runway | | | | x | | + | runway | yes | | | x | | + | runway | no | | | | | + | runway | | yes | | x | | + | runway | | no | | | | + | runway | no | yes | | x | | + | runway | yes | no | | | | + | runway | | | yes | x | | + | runway | | | no | | | + | runway | no | | yes | x | | + | runway | yes | | no | | | + | runway | | no | yes | x | | + | runway | | yes | no | | | + + @todo + Scenario: Bike - Access tag in backward direction + Then routability should be + | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw | + | | | | | | 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 | | | + | runway | | | | | x | + | runway | yes | | | | x | + | runway | no | | | | | + | runway | | yes | | | x | + | runway | | no | | | | + | runway | no | yes | | | x | + | runway | yes | no | | | | + | runway | | | yes | | x | + | runway | | | no | | | + | runway | no | | yes | | x | + | runway | yes | | no | | | + | runway | | no | yes | | x | + | runway | | yes | no | | | Scenario: Bike - Overwriting implied acccess on ways Then routability should be @@ -51,18 +109,6 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access | runway | | yes | | x | | runway | | | yes | x | - Scenario: Bike - Overwriting implied acccess on nodes - Then routability should be - | highway | node/access | node/vehicle | node/bicycle | bothw | - | cycleway | | | | x | - | runway | | | | | - | cycleway | no | | | | - | cycleway | | no | | | - | cycleway | | | no | | - | runway | yes | | | | - | runway | | yes | | | - | runway | | | yes | | - Scenario: Bike - Access tags on ways Then routability should be | access | vehicle | bicycle | bothw | @@ -92,35 +138,6 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access | | | agricultural | | | | | forestery | | - Scenario: Bike - Access tags on nodes - Then routability should be - | node/access | node/vehicle | node/bicycle | bothw | - | | | | x | - | yes | | | x | - | permissive | | | x | - | designated | | | x | - | some_tag | | | x | - | no | | | | - | private | | | | - | agricultural | | | | - | forestery | | | | - | | yes | | x | - | | permissive | | x | - | | designated | | x | - | | some_tag | | x | - | | no | | | - | | private | | | - | | agricultural | | | - | | forestery | | | - | | | yes | x | - | | | permissive | x | - | | | designated | x | - | | | some_tag | x | - | | | no | | - | | | private | | - | | | agricultural | | - | | | forestery | | - Scenario: Bike - Access tags on both node and way Then routability should be | access | node/access | bothw | @@ -147,10 +164,10 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access Scenario: Bike - Ignore access tags for other modes Then routability should be - | highway | foot | motor_vehicle | moped | bothw | - | runway | yes | | | | + | highway | boat | motor_vehicle | moped | bothw | + | river | yes | | | | | cycleway | no | | | x | | runway | | yes | | | | cycleway | | no | | x | | runway | | | yes | | - | cycleway | | | no | x | \ No newline at end of file + | cycleway | | | no | x | diff --git a/features/bicycle/access_node.feature b/features/bicycle/access_node.feature new file mode 100644 index 000000000..eba808d52 --- /dev/null +++ b/features/bicycle/access_node.feature @@ -0,0 +1,64 @@ +@routing @bicycle @access +Feature: Bike - Access tags on nodes +Reference: http://wiki.openstreetmap.org/wiki/Key:access + + Background: + Given the profile "bicycle" + + 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 | | + + Scenario: Bike - Overwriting implied acccess on nodes + Then routability should be + | highway | node/access | node/vehicle | node/bicycle | bothw | + | cycleway | | | | x | + | runway | | | | | + | cycleway | no | | | | + | cycleway | | no | | | + | cycleway | | | no | | + | runway | yes | | | | + | runway | | yes | | | + | runway | | | yes | | + + Scenario: Bike - Access tags on nodes + Then routability should be + | node/access | node/vehicle | node/bicycle | bothw | + | | | | x | + | yes | | | x | + | permissive | | | x | + | designated | | | x | + | some_tag | | | x | + | no | | | | + | private | | | | + | agricultural | | | | + | forestery | | | | + | | yes | | x | + | | permissive | | x | + | | designated | | x | + | | some_tag | | x | + | | no | | | + | | private | | | + | | agricultural | | | + | | forestery | | | + | | | yes | x | + | | | permissive | x | + | | | designated | x | + | | | some_tag | x | + | | | no | | + | | | private | | + | | | agricultural | | + | | | forestery | | \ No newline at end of file diff --git a/features/bicycle/cycleway.feature b/features/bicycle/cycleway.feature index bf42563ff..f26029453 100644 --- a/features/bicycle/cycleway.feature +++ b/features/bicycle/cycleway.feature @@ -29,16 +29,16 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway Then routability should be | highway | cycleway | cycleway:left | cycleway:right | forw | backw | | primary | | | | x | x | - | pirmary | track | | | x | x | - | pirmary | opposite | | | x | x | - | pirmary | | track | | x | x | - | pirmary | | opposite | | x | x | - | pirmary | | | track | x | x | - | pirmary | | | opposite | x | x | - | pirmary | | track | track | x | x | - | pirmary | | opposite | opposite | x | x | - | pirmary | | track | opposite | x | x | - | pirmary | | opposite | track | x | x | + | primary | track | | | x | x | + | primary | opposite | | | x | x | + | primary | | track | | x | x | + | primary | | opposite | | x | x | + | primary | | | track | x | x | + | primary | | | opposite | x | x | + | primary | | track | track | x | x | + | primary | | opposite | opposite | x | x | + | primary | | track | opposite | x | x | + | primary | | opposite | track | x | x | Scenario: Bike - Left/right side cycleways on implied oneways Then routability should be diff --git a/features/bicycle/oneway.feature b/features/bicycle/oneway.feature index 4e6cb4f2d..6a9d3bf02 100644 --- a/features/bicycle/oneway.feature +++ b/features/bicycle/oneway.feature @@ -1,19 +1,20 @@ @routing @bicycle @oneway Feature: Bike - Oneway streets Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing +Usually we can push bikes against oneways, but we use foot=no to prevent this in these tests Background: Given the profile "bicycle" Scenario: Bike - Simple oneway Then routability should be - | highway | oneway | forw | backw | - | primary | yes | x | | + | highway | foot | oneway | forw | backw | + | primary | no | yes | x | | Scenario: Simple reverse oneway Then routability should be - | highway | oneway | forw | backw | - | primary | -1 | | x | + | highway | foot | oneway | forw | backw | + | primary | no | -1 | | x | Scenario: Bike - Around the Block Given the node map @@ -21,11 +22,11 @@ Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tag | d | c | And the ways - | nodes | oneway | - | ab | yes | - | bc | | - | cd | | - | da | | + | nodes | oneway | foot | + | ab | yes | no | + | bc | | no | + | cd | | no | + | da | | no | When I route I should get | from | to | route | @@ -34,80 +35,80 @@ Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tag Scenario: Bike - Handle various oneway tag values Then routability should be - | oneway | forw | backw | - | | x | x | - | nonsense | x | x | - | no | x | x | - | false | x | x | - | 0 | x | x | - | yes | x | | - | true | x | | - | 1 | x | | - | -1 | | x | + | foot | oneway | forw | backw | + | no | | x | x | + | no | nonsense | x | x | + | no | no | x | x | + | no | false | x | x | + | no | 0 | x | x | + | no | yes | x | | + | no | true | x | | + | no | 1 | x | | + | no | -1 | | x | Scenario: Bike - Implied oneways Then routability should be - | highway | bicycle | junction | forw | backw | - | | | | x | x | - | | | roundabout | x | | - | motorway | yes | | x | | - | motorway_link | yes | | x | | - | motorway | yes | roundabout | x | | - | motorway_link | yes | roundabout | x | | + | highway | foot | bicycle | junction | forw | backw | + | | no | | | x | x | + | | no | | roundabout | x | | + | motorway | no | yes | | x | | + | motorway_link | no | yes | | x | | + | motorway | no | yes | roundabout | x | | + | motorway_link | no | yes | roundabout | x | | Scenario: Bike - Overriding implied oneways Then routability should be - | highway | junction | oneway | forw | backw | - | primary | roundabout | no | x | x | - | primary | roundabout | yes | x | | - | motorway_link | | -1 | | | - | trunk_link | | -1 | | | - | primary | roundabout | -1 | | x | + | highway | foot | junction | oneway | forw | backw | + | primary | no | roundabout | no | x | x | + | primary | no | roundabout | yes | x | | + | motorway_link | no | | -1 | | | + | trunk_link | no | | -1 | | | + | primary | no | roundabout | -1 | | x | Scenario: Bike - Oneway:bicycle should override normal oneways tags Then routability should be - | oneway:bicycle | oneway | junction | forw | backw | - | yes | | | x | | - | yes | yes | | x | | - | yes | no | | x | | - | yes | -1 | | x | | - | yes | | roundabout | x | | - | no | | | x | x | - | no | yes | | x | x | - | no | no | | x | x | - | no | -1 | | x | x | - | no | | roundabout | x | x | - | -1 | | | | x | - | -1 | yes | | | x | - | -1 | no | | | x | - | -1 | -1 | | | x | - | -1 | | roundabout | | x | + | foot | oneway:bicycle | oneway | junction | forw | backw | + | no | yes | | | x | | + | no | yes | yes | | x | | + | no | yes | no | | x | | + | no | yes | -1 | | x | | + | no | yes | | roundabout | x | | + | no | no | | | x | x | + | no | no | yes | | x | x | + | no | no | no | | x | x | + | no | no | -1 | | x | x | + | no | no | | roundabout | x | x | + | no | -1 | | | | x | + | no | -1 | yes | | | x | + | no | -1 | no | | | x | + | no | -1 | -1 | | | x | + | no | -1 | | roundabout | | x | Scenario: Bike - Contra flow Then routability should be - | oneway | cycleway | forw | backw | - | yes | opposite | x | x | - | yes | opposite_track | x | x | - | yes | opposite_lane | x | x | - | -1 | opposite | x | x | - | -1 | opposite_track | x | x | - | -1 | opposite_lane | x | x | - | no | opposite | x | x | - | no | opposite_track | x | x | - | no | opposite_lane | x | x | + | foot | oneway | cycleway | forw | backw | + | no | yes | opposite | x | x | + | no | yes | opposite_track | x | x | + | no | yes | opposite_lane | x | x | + | no | -1 | opposite | x | x | + | no | -1 | opposite_track | x | x | + | no | -1 | opposite_lane | x | x | + | no | no | opposite | x | x | + | no | no | opposite_track | x | x | + | no | no | opposite_lane | x | x | Scenario: Bike - Should not be affected by car tags Then routability should be - | junction | oneway | oneway:car | forw | backw | - | | yes | yes | x | | - | | yes | no | x | | - | | yes | -1 | x | | - | | no | yes | x | x | - | | no | no | x | x | - | | no | -1 | x | x | - | | -1 | yes | | x | - | | -1 | no | | x | - | | -1 | -1 | | x | - | roundabout | | yes | x | | - | roundabout | | no | x | | - | roundabout | | -1 | x | | + | foot | junction | oneway | oneway:car | forw | backw | + | no | | yes | yes | x | | + | no | | yes | no | x | | + | no | | yes | -1 | x | | + | no | | no | yes | x | x | + | no | | no | no | x | x | + | no | | no | -1 | x | x | + | no | | -1 | yes | | x | + | no | | -1 | no | | x | + | no | | -1 | -1 | | x | + | no | roundabout | | yes | x | | + | no | roundabout | | no | x | | + | no | roundabout | | -1 | x | | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature new file mode 100644 index 000000000..37dff3d1f --- /dev/null +++ b/features/bicycle/pushing.feature @@ -0,0 +1,72 @@ +@routing @bicycle @pushing +Feature: Bike - Accessability of different way types + + Background: + Given the profile "bicycle" + Given the shortcuts + | key | value | + | bike | 40s ~20% | + | foot | 180s ~20% | + + Scenario: Bike - Pushing bikes on pedestrian-only ways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | cycleway | | bike | bike | + | primary | | bike | bike | + | pedestrian | | foot | foot | + | footway | | foot | foot | + | primary | yes | bike | foot | + + Scenario: Bike - Pushing bikes against normal oneways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | primary | yes | bike | foot | + | pedestrian | yes | foot | foot | + + Scenario: Bike - Pushing bikes against reverse oneways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | primary | -1 | foot | bike | + | pedestrian | -1 | foot | foot | + + @square + Scenario: Bike - Push bikes on pedestrian areas + Given the node map + | x | | + | a | b | + | d | c | + + And the ways + | nodes | area | highway | + | xa | | primary | + | abcda | yes | pedestrian | + + When I route I should get + | from | to | route | + | a | b | abcda | + | a | d | abcda | + | b | c | abcda | + | c | b | abcda | + | c | d | abcda | + | d | c | abcda | + | d | a | abcda | + | a | d | abcda | + + Scenario: Bike - Pushing bikes on ways with foot=yes + Then routability should be + | highway | foot | bothw | + | motorway | | | + | motorway | yes | foot | + | runway | | | + | runway | yes | foot | + + @todo + Scenario: Bike - Pushing bikes on ways with foot=yes in one direction + Then routability should be + | highway | foot:forward | foot:backward | forw | backw | + | motorway | | | | | + | motorway | yes | | foot | | + | motorway | | yes | | foot | diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index 6c5daf70b..27c5c353e 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -3,7 +3,7 @@ Feature: Bike - Turn restrictions Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes. - Background: Use car routing + Background: Given the profile "bicycle" @no_turning @@ -14,11 +14,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -38,11 +38,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -62,11 +62,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -86,11 +86,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -110,11 +110,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -134,11 +134,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -158,11 +158,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -182,11 +182,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -206,13 +206,13 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | no | - | xj | -1 | - | aj | -1 | - | bj | no | - | cj | -1 | - | dj | -1 | + | nodes | oneway | foot | + | sj | no | no | + | xj | -1 | no | + | aj | -1 | no | + | bj | no | no | + | cj | -1 | no | + | dj | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | except | @@ -236,10 +236,10 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | aj | no | - | bj | no | + | nodes | oneway | foot | + | sj | yes | no | + | aj | no | no | + | bj | no | no | And the relations | type | way:from | way:to | node:via | restriction | except | @@ -261,14 +261,14 @@ Feature: Bike - Turn restrictions | | | f | And the ways - | nodes | oneway | - | sj | yes | - | ja | yes | - | jb | yes | - | jc | yes | - | jd | yes | - | je | yes | - | jf | yes | + | nodes | oneway | foot | + | sj | yes | no | + | ja | yes | no | + | jb | yes | no | + | jc | yes | no | + | jd | yes | no | + | je | yes | no | + | jf | yes | no | And the relations | type | way:from | way:to | node:via | restriction | except | diff --git a/features/bicycle/way.feature b/features/bicycle/way.feature index ca157bd25..f5ad5bb87 100644 --- a/features/bicycle/way.feature +++ b/features/bicycle/way.feature @@ -4,32 +4,38 @@ Feature: Bike - Accessability of different way types Background: Given the profile "bicycle" - Scenario: Bike - Basic access + Scenario: Bike - Routability of way types Bikes are allowed on footways etc because you can pull your bike at a lower speed. - Given the profile "bicycle" + Pier is not allowed, since it's tagged using man_made=pier. Then routability should be - | highway | forw | - | (nil) | | - | motorway | | - | motorway_link | | - | trunk | | - | trunk_link | | - | primary | x | - | primary_link | x | - | secondary | x | - | secondary_link | x | - | tertiary | x | - | tertiary_link | x | - | residential | x | - | service | x | - | unclassified | x | - | living_street | x | - | road | x | - | track | x | - | path | x | - | footway | x | - | pedestrian | x | - | steps | x | - | pier | x | - | cycleway | x | - | bridleway | | + | highway | bothw | + | (nil) | | + | motorway | | + | motorway_link | | + | trunk | | + | trunk_link | | + | primary | x | + | primary_link | x | + | secondary | x | + | secondary_link | x | + | tertiary | x | + | tertiary_link | x | + | residential | x | + | service | x | + | unclassified | x | + | living_street | x | + | road | x | + | track | x | + | path | x | + | footway | x | + | pedestrian | x | + | steps | x | + | cycleway | x | + | bridleway | | + | pier | | + + Scenario: Bike - Routability of man_made structures + Then routability should be + | highway | man_made | bothw | + | (nil) | (nil) | | + | (nil) | pier | x | diff --git a/features/car/permissive.feature b/features/car/permissive.feature new file mode 100644 index 000000000..e69de29bb diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 6038126ee..8c518a6f0 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -12,7 +12,9 @@ restriction_exception_tags = { "bicycle", "vehicle", "access" } default_speed = 16 -main_speeds = { +walking_speed = 4 + +bicycle_speeds = { ["cycleway"] = 18, ["primary"] = 17, ["primary_link"] = 17, @@ -26,17 +28,14 @@ main_speeds = { ["road"] = 16, ["service"] = 16, ["track"] = 13, - ["path"] = 13, - ["footway"] = 12, - ["pedestrian"] = 12, - ["pier"] = 12, - ["steps"] = 2 + ["path"] = 13 + --["footway"] = 12, + --["pedestrian"] = 12, } pedestrian_speeds = { - ["footway"] = 5, - ["pedestrian"] = 5, - ["pier"] = 5, + ["footway"] = walking_speed, + ["pedestrian"] = walking_speed, ["steps"] = 2 } @@ -50,7 +49,7 @@ railway_speeds = { } platform_speeds = { - ["platform"] = 5 + ["platform"] = walking_speed } amenity_speeds = { @@ -58,6 +57,10 @@ amenity_speeds = { ["parking_entrance"] = 10 } +man_made_speeds = { + ["pier"] = walking_speed +} + route_speeds = { ["ferry"] = 5 } @@ -110,17 +113,36 @@ function way_function (way, numberOfNodesInWay) if(numberOfNodesInWay < 2) then return 0; end - - -- First, get the properties of each way that we come across + + -- initial routability check, filters out buildings, boundaries, etc local highway = way.tags:Find("highway") + local route = way.tags:Find("route") + local man_made = way.tags:Find("man_made") + local railway = way.tags:Find("railway") + local amenity = way.tags:Find("amenity") + local public_transport = way.tags:Find("public_transport") + if (not highway or highway == '') and + (not route or route == '') and + (not railway or railway=='') and + (not amenity or amenity=='') and + (not man_made or man_made=='') and + (not public_transport or public_transport=='') + then + return 0 + end + + -- access + local access = Access.find_access_tag(way, access_tags_hierachy) + if access_tag_blacklist[access] then + return 0 + end + + + -- other tags local name = way.tags:Find("name") local ref = way.tags:Find("ref") local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local railway = way.tags:Find("railway") - local public_transport = way.tags:Find("public_transport") local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) - local man_made = way.tags:Find("man_made") local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") local onewayClass = way.tags:Find("oneway:bicycle") @@ -130,23 +152,7 @@ function way_function (way, numberOfNodesInWay) local duration = way.tags:Find("duration") local service = way.tags:Find("service") local area = way.tags:Find("area") - local amenity = way.tags:Find("amenity") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- initial routability check, filters out buildings, boundaries, etc - if (not highway or highway == '') and - (not route or route == '') and - (not railway or railway=='') and - (not amenity or amenity=='') and - (not public_transport or public_transport=='') - then - return 0 - end - - -- access - if access_tag_blacklist[access] then - return 0 - end + local foot = way.tags:Find("foot") -- name if "" ~= ref then @@ -157,8 +163,9 @@ function way_function (way, numberOfNodesInWay) way.name = highway -- if no name exists, use way type end + -- speed if route_speeds[route] then - -- ferries + -- ferries (doesn't cover routes tagged using relations) way.direction = Way.bidirectional way.ignore_in_grid = true if durationIsValid(duration) then @@ -179,34 +186,32 @@ function way_function (way, numberOfNodesInWay) way.speed = railway_speeds[railway] way.direction = Way.bidirectional end - elseif pedestrian_speeds[highway] and main_speeds[highway] then - -- pedestrian areas - if access_tag_whitelist[access] then - way.speed = main_speeds[highway] -- biking - else - way.speed = pedestrian_speeds[highway] -- pushing bikes - end elseif amenity and amenity_speeds[amenity] then -- parking areas way.speed = amenity_speeds[amenity] - else + elseif bicycle_speeds[highway] then -- regular ways - if main_speeds[highway] then - way.speed = main_speeds[highway] - elseif main_speeds[man_made] then - way.speed = main_speeds[man_made] - elseif access_tag_whitelist[access] then - way.speed = default_speed - end - end - - -- maxspeed - if take_minimum_of_speeds then - if maxspeed and maxspeed>0 then - way.speed = math.min(way.speed, maxspeed) - end - end - + way.speed = bicycle_speeds[highway] + elseif access and access_tag_whitelist[access] then + -- unknown way, but valid access tag + way.speed = default_speed + else + -- biking not allowed, maybe we can push our bike? + -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike + -- TODO: if we can push, the way should be marked as pedestrion mode, but there's no way to do it yet from lua.. + if foot ~= 'no' then + if pedestrian_speeds[highway] then + -- pedestrian-only ways and areas + way.speed = pedestrian_speeds[highway] + elseif man_made and man_made_speeds[man_made] then + -- man made structures + way.speed = man_made_speeds[man_made] + elseif foot == 'yes' then + way.speed = walking_speed + end + end + end + -- direction way.direction = Way.bidirectional local impliedOneway = false @@ -249,15 +254,40 @@ function way_function (way, numberOfNodesInWay) way.direction = Way.oneway end + -- pushing bikes + if bicycle_speeds[highway] or pedestrian_speeds[highway] then + if foot ~= 'no' then + if way.direction == Way.oneway then + way.backward_speed = walking_speed + elseif way.direction == Way.opposite then + way.backward_speed = walking_speed + way.speed = way.speed + end + end + if way.backward_speed == way.speed then + -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal + way.direction = Way.bidirectional + end + end + + -- cycleways if cycleway and cycleway_tags[cycleway] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] elseif cycleway_left and cycleway_tags[cycleway_left] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] elseif cycleway_right and cycleway_tags[cycleway_right] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] end + -- maxspeed + -- TODO: maxspeed of backward direction + if take_minimum_of_speeds then + if maxspeed and maxspeed>0 then + way.speed = math.min(way.speed, maxspeed) + end + end + way.type = 1 return 1 end From 5b5e9296b330ac922c4df281f5ea4330d1ce308d Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 14:54:22 +0100 Subject: [PATCH 097/161] Adding const to parameter and rehash to give map 1000 buckets --- DataStructures/BinaryHeap.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/DataStructures/BinaryHeap.h b/DataStructures/BinaryHeap.h index 85c14d456..f8b34704f 100644 --- a/DataStructures/BinaryHeap.h +++ b/DataStructures/BinaryHeap.h @@ -75,10 +75,13 @@ template< typename NodeID, typename Key > class UnorderedMapStorage { public: - UnorderedMapStorage( size_t ) { } + UnorderedMapStorage( size_t ) { + //hash table gets 1000 Buckets + nodes.rehash(1000); + } - Key &operator[]( NodeID node ) { - return nodes[node]; + Key &operator[]( const NodeID node ) { + return nodes[node]; } void Clear() { From 405600783e3da05ff1a4f035cfd7d9207d7a738f Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 14:55:49 +0100 Subject: [PATCH 098/161] introducing further typedefs to make code more readable --- DataStructures/SearchEngine.h | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h index bd3e42005..505d3f905 100644 --- a/DataStructures/SearchEngine.h +++ b/DataStructures/SearchEngine.h @@ -42,32 +42,33 @@ struct _HeapData { _HeapData( NodeID p ) : parent(p) { } }; -typedef boost::thread_specific_ptr > > SearchEngineHeapPtr; +typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage > QueryHeapType; +typedef boost::thread_specific_ptr SearchEngineHeapPtr; template struct SearchEngineData { - typedef SearchEngineHeapPtr HeapPtr; typedef GraphT Graph; + typedef QueryHeapType QueryHeap; SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) :graph(g), nodeHelpDesk(nh), names(n) {} const GraphT * graph; NodeInformationHelpDesk * nodeHelpDesk; std::vector & names; - static HeapPtr forwardHeap; - static HeapPtr backwardHeap; - static HeapPtr forwardHeap2; - static HeapPtr backwardHeap2; - static HeapPtr forwardHeap3; - static HeapPtr backwardHeap3; + static SearchEngineHeapPtr forwardHeap; + static SearchEngineHeapPtr backwardHeap; + static SearchEngineHeapPtr forwardHeap2; + static SearchEngineHeapPtr backwardHeap2; + static SearchEngineHeapPtr forwardHeap3; + static SearchEngineHeapPtr backwardHeap3; inline void InitializeOrClearFirstThreadLocalStorage() { if(!forwardHeap.get()) { - forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else forwardHeap->Clear(); if(!backwardHeap.get()) { - backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else backwardHeap->Clear(); @@ -75,13 +76,13 @@ struct SearchEngineData { inline void InitializeOrClearSecondThreadLocalStorage() { if(!forwardHeap2.get()) { - forwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else forwardHeap2->Clear(); if(!backwardHeap2.get()) { - backwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else backwardHeap2->Clear(); @@ -89,13 +90,13 @@ struct SearchEngineData { inline void InitializeOrClearThirdThreadLocalStorage() { if(!forwardHeap3.get()) { - forwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else forwardHeap3->Clear(); if(!backwardHeap3.get()) { - backwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage >(nodeHelpDesk->getNumberOfNodes())); + backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); } else backwardHeap3->Clear(); From 26729ca48289eb7aae8548ac8b4e8eab94d741f7 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 14:57:40 +0100 Subject: [PATCH 099/161] Fixing useless comparison --- Extractor/ExtractorCallbacks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 956a9fee4..1702ec0d5 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -67,7 +67,7 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { bool ExtractorCallbacks::wayFunction(_Way &w) { /*** Store name of way and split it into edge segments ***/ - if ( 0 < w.speed > 0 || 0 < w.duration ) { //Only true if the way is specified by the speed profile + if ( (0 < w.speed) || (0 < w.duration) ) { //Only true if the way is specified by the speed profile //Get the unique identifier for the street name const StringMap::const_iterator strit = stringMap->find(w.name); if(strit == stringMap->end()) { From 7d9d0878de2663a7f0109edad37f2a737c800571 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 14:59:10 +0100 Subject: [PATCH 100/161] Adding templated utility functions for repeated operations on containers --- Util/ContainerUtils.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Util/ContainerUtils.h diff --git a/Util/ContainerUtils.h b/Util/ContainerUtils.h new file mode 100644 index 000000000..215e9885c --- /dev/null +++ b/Util/ContainerUtils.h @@ -0,0 +1,34 @@ +/* + * ContainerUtils.h + * + * Created on: 02.02.2013 + * Author: dennis + */ + +#ifndef CONTAINERUTILS_H_ +#define CONTAINERUTILS_H_ + +#include +#include + +template +inline void sort_unique_resize(std::vector & vector) { + std::sort(vector.begin(), vector.end()); + unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin(); + vector.resize(number_of_unique_elements); +} + +template +inline void sort_unique_resize_shrink_vector(std::vector & vector) { + sort_unique_resize(vector); + std::vector().swap(vector); +} + +template +inline void remove_consecutive_duplicates_from_vector(std::vector & vector) { + unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin(); + vector.resize(number_of_unique_elements); +} + + +#endif /* CONTAINERUTILS_H_ */ From 3a4695713d9b27c566e47c6d809049b00f410bbb Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 15:34:41 +0100 Subject: [PATCH 101/161] test bike maxspeed forw/backw (@todo) --- features/bicycle/maxspeed.feature | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 30d82b7e8..9ca10006b 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -31,3 +31,25 @@ Feature: Bike - Max speed restrictions | from | to | route | time | | a | b | ab | 20s ~5% | | b | c | bc | 20s ~5% | + + @todo + Scenario: Bike - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | f | g | h | + + And the shortcuts + | key | value | + | bike | 43s ~10% | + | run | 73s ~10% | + | walk | 170s ~10% | + | snail | 720s ~10% | + + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | bike | bike | + | 10 | | | run | run | + | | 10 | | run | bike | + | | | 10 | bike | run | + | 1 | 10 | | run | snail | + | 1 | | 10 | snail | run | + | 1 | 5 | 10 | walk | run | From c453f8e7a94a75407aa2531142bbd706993b8bc9 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 15:42:14 +0100 Subject: [PATCH 102/161] test car maxspeed forw/backw (@todo) --- features/car/maxspeed.feature | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 8e40e95bf..55de6bd8a 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -32,3 +32,27 @@ Feature: Car - Max speed restrictions | from | to | route | time | | a | b | ab | 144s ~10% | | b | c | bc | 144s ~10% | + + @todo + Scenario: Car - Forward/backward maxspeed + Given the node map + | a | b | c | d | e | f | g | h | + + And a grid size of 100 meters + + And the shortcuts + | key | value | + | car | 12s ~10% | + | run | 73s ~10% | + | walk | 170s ~10% | + | snail | 720s ~10% | + + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | car | car | + | 10 | | | run | run | + | | 10 | | run | car | + | | | 10 | car | run | + | 1 | 10 | | run | snail | + | 1 | | 10 | snail | run | + | 1 | 5 | 10 | walk | run | From f7505e887741339888052f3afc6a32187fffa32e Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 15:43:12 +0100 Subject: [PATCH 103/161] test car maxspeed forw/backw (@todo) --- features/bicycle/maxspeed.feature | 5 +---- features/car/maxspeed.feature | 9 +++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 9ca10006b..892daeba4 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -34,10 +34,7 @@ Feature: Bike - Max speed restrictions @todo Scenario: Bike - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | f | g | h | - - And the shortcuts + Given the shortcuts | key | value | | bike | 43s ~10% | | run | 73s ~10% | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 55de6bd8a..f0d038724 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -35,17 +35,14 @@ Feature: Car - Max speed restrictions @todo Scenario: Car - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | f | g | h | - - And a grid size of 100 meters - - And the shortcuts + Given the shortcuts | key | value | | car | 12s ~10% | | run | 73s ~10% | | walk | 170s ~10% | | snail | 720s ~10% | + + And a grid size of 100 meters Then routability should be | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | From 2dbae6ce5106749d30ef24886333eaa6d5d1e712 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 16:47:32 +0100 Subject: [PATCH 104/161] Refactoring routing algorithms, alternative computation hastened by sweeping the search space only once. Should fix #572 --- RoutingAlgorithms/AlternativePathRouting.h | 337 ++++++++++++--------- RoutingAlgorithms/BasicRoutingInterface.h | 72 +++-- RoutingAlgorithms/ShortestPathRouting.h | 130 ++------ 3 files changed, 259 insertions(+), 280 deletions(-) diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h index b55d1a9aa..bd542e1a3 100644 --- a/RoutingAlgorithms/AlternativePathRouting.h +++ b/RoutingAlgorithms/AlternativePathRouting.h @@ -21,23 +21,25 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef ALTERNATIVEROUTES_H_ #define ALTERNATIVEROUTES_H_ +#include +#include #include #include "BasicRoutingInterface.h" -const double VIAPATH_ALPHA = 0.25; -const double VIAPATH_EPSILON = 0.25; -const double VIAPATH_GAMMA = 0.80; +const double VIAPATH_ALPHA = 0.15; +const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer +const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest. template -class AlternativeRouting : private BasicRoutingInterface{ +class AlternativeRouting : private BasicRoutingInterface { typedef BasicRoutingInterface super; - typedef std::pair PreselectedNode; - typedef typename QueryDataT::HeapPtr HeapPtr; - typedef std::pair UnpackEdge; + typedef typename QueryDataT::Graph SearchGraph; + typedef typename QueryDataT::QueryHeap QueryHeap; + typedef std::pair SearchSpaceEdge; struct RankedCandidateNode { - RankedCandidateNode(NodeID n, int l, int s) : node(n), length(l), sharing(s) {} + RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {} NodeID node; int length; int sharing; @@ -45,9 +47,12 @@ class AlternativeRouting : private BasicRoutingInterface{ return (2*length + sharing) < (2*other.length + other.sharing); } }; + + const SearchGraph * search_graph; + public: - AlternativeRouting(QueryDataT & qd) : super(qd) { } + AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { } ~AlternativeRouting() {} @@ -59,81 +64,115 @@ public: std::vector alternativePath; std::vector viaNodeCandidates; - std::vector packedShortestPath; - std::vector nodesThatPassPreselection; + std::vector forward_search_space; + std::vector reverse_search_space; - HeapPtr & forwardHeap = super::_queryData.forwardHeap; - HeapPtr & backwardHeap = super::_queryData.backwardHeap; - HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2; - HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2; - - //Initialize Queues + //Initialize Queues, semi-expensive because access to TSS invokes a system call super::_queryData.InitializeOrClearFirstThreadLocalStorage(); - int _upperBound = INT_MAX; - NodeID middle = UINT_MAX; - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + super::_queryData.InitializeOrClearSecondThreadLocalStorage(); + super::_queryData.InitializeOrClearThirdThreadLocalStorage(); + + QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap); + QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap); + QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2); + QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2); + + int upper_bound_to_shortest_path_distance = INT_MAX; + NodeID middle_node = UINT_MAX; + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); if(phantomNodePair.startPhantom.isBidirected() ) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); } - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); + reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); if(phantomNodePair.targetPhantom.isBidirected() ) { - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); + reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } - const int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) - + (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1); + const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0); + const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0); //exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while(forwardHeap->Size() + backwardHeap->Size() > 0){ - if(forwardHeap->Size() > 0){ - AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates); + while(0 < (forward_heap1.Size() + reverse_heap1.Size())){ + if(0 < forward_heap1.Size()){ + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset); } - if(backwardHeap->Size() > 0){ - AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates); + if(0 < reverse_heap1.Size()){ + AlternativeRoutingStep(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset); } } - std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end()); - int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin(); - viaNodeCandidates.resize(size); + sort_unique_resize(viaNodeCandidates); - //save (packed) shortest path of shortest path and keep it for later use. - //we need it during the checks and dont want to recompute it always - super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath); + std::vector packed_forward_path; + std::vector packed_reverse_path; - //ch-pruning of via nodes in both search spaces + super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path); + super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path); + boost::unordered_map approximated_forward_sharing; + boost::unordered_map approximated_reverse_sharing; + + unsigned index_into_forward_path = 0; + //sweep over search space, compute forward sharing for each current edge (u,v) + BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) { + //current_edge is on shortest path => sharing(u):=queue.GetKey(u); + ++index_into_forward_path; + approximated_forward_sharing[v] = forward_heap1.GetKey(u); + } else { + //sharing (s) = sharing (t) + approximated_forward_sharing[v] = approximated_forward_sharing[u]; + } + } + + unsigned index_into_reverse_path = 0; + //sweep over search space, compute backward sharing + BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) { + const NodeID u = current_edge.first; + const NodeID v = current_edge.second; + if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) { + //current_edge is on shortest path => sharing(u):=queue.GetKey(u); + ++index_into_reverse_path; + approximated_reverse_sharing[v] = reverse_heap1.GetKey(u); + } else { + //sharing (s) = sharing (t) + approximated_reverse_sharing[v] = approximated_reverse_sharing[u]; + } + } + std::vector nodes_that_passed_preselection; BOOST_FOREACH(const NodeID node, viaNodeCandidates) { - if(node == middle) //subpath optimality tells us that this case is just the shortest path - continue; + int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node]; + int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node); + bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)); + bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA); + bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing); - int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath); - int length1 = forwardHeap->GetKey(node); - int length2 = backwardHeap->GetKey(node); - bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON)); - bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA); - bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing); - - if(lengthPassed && sharingPassed && stretchPassed) - nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2)); + if(lengthPassed && sharingPassed && stretchPassed) { + nodes_that_passed_preselection.push_back(node); + } } + std::vector & packedShortestPath = packed_forward_path; + std::reverse(packedShortestPath.begin(), packedShortestPath.end()); + packedShortestPath.push_back(middle_node); + packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end()); std::vector rankedCandidates; //prioritizing via nodes for deep inspection - BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) { + BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) { int lengthOfViaPath = 0, sharingOfViaPath = 0; - - computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath); - if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound) - rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath)); + computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath); + if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) { + rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath)); + } } - std::sort(rankedCandidates.begin(), rankedCandidates.end()); NodeID selectedViaNode = UINT_MAX; int lengthOfViaPath = INT_MAX; NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX; - BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){ - if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { + BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){ + if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { // select first admissable selectedViaNode = candidate.node; break; @@ -141,15 +180,15 @@ public: } //Unpack shortest path and alternative, if they exist - if(INT_MAX != _upperBound) { + if(INT_MAX != upper_bound_to_shortest_path_distance) { super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath); - rawRouteData.lengthOfShortestPath = _upperBound; + rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance; } else { rawRouteData.lengthOfShortestPath = INT_MAX; } if(selectedViaNode != UINT_MAX) { - retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath); + retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath); rawRouteData.lengthOfAlternativePath = lengthOfViaPath; } else { rawRouteData.lengthOfAlternativePath = INT_MAX; @@ -158,7 +197,7 @@ public: private: //unpack by exploring search spaces from v - inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2, + inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2, const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) { //unpack [s,v) std::vector packed_s_v_path, packed_v_t_path; @@ -170,16 +209,16 @@ private: super::UnpackPath(packed_s_v_path, unpackedPath); } - inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, - const int offset, const std::vector & packedShortestPath) { + inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path, + const int offset, const std::vector & packed_shortest_path) { //compute and unpack and by exploring search spaces from v and intersecting against queues //only half-searches have to be done at this stage super::_queryData.InitializeOrClearSecondThreadLocalStorage(); - HeapPtr & existingForwardHeap = super::_queryData.forwardHeap; - HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap; - HeapPtr & newForwardHeap = super::_queryData.forwardHeap2; - HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2; + QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap; + QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap; + QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2; + QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2; std::vector < NodeID > packed_s_v_path; std::vector < NodeID > packed_v_t_path; @@ -189,18 +228,18 @@ private: NodeID s_v_middle = UINT_MAX; int upperBoundFor_s_v_Path = INT_MAX;//compute path by reusing forward search from s - newBackwardHeap->Insert(node.first, 0, node.first); - while (newBackwardHeap->Size() > 0) { + newBackwardHeap.Insert(via_node, 0, via_node); + while (0 < newBackwardHeap.Size()) { super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false); } //compute path by reusing backward search from node t NodeID v_t_middle = UINT_MAX; int upperBoundFor_v_t_Path = INT_MAX; - newForwardHeap->Insert(node.first, 0, node.first); - while (newForwardHeap->Size() > 0) { + newForwardHeap.Insert(via_node, 0, via_node); + while (0 < newForwardHeap.Size() ) { super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true); } - *lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path; + *real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path; if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle) return; @@ -211,35 +250,35 @@ private: //partial unpacking, compute sharing //First partially unpack s-->v until paths deviate, note length of common path. - for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.size()) - 1; (i < lengthOfPackedPath); ++i) { - if (packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) { + if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) { + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { - if (packed_s_v_path[i] == packedShortestPath[i]) { + if (packed_s_v_path[i] == packed_shortest_path[i]) { super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath); - super::UnpackEdge(packedShortestPath[i], packedShortestPath[i+1], partiallyUnpackedShortestPath); + super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath); break; } } } //traverse partially unpacked edge and note common prefix for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } //Second, partially unpack v-->t in reverse order until paths deviate and note lengths int viaPathIndex = packed_v_t_path.size() - 1; - int shortestPathIndex = packedShortestPath.size() - 1; + int shortestPathIndex = packed_shortest_path.size() - 1; for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) { - if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { - if (packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) { + if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath); - super::UnpackEdge(packedShortestPath[shortestPathIndex-1] , packedShortestPath[shortestPathIndex], partiallyUnpackedShortestPath); + super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath); break; } } @@ -249,16 +288,16 @@ private: shortestPathIndex = partiallyUnpackedShortestPath.size() - 1; for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) { if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]); - *sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]); + *sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance; } else { break; } } - //finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable + //finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable } - inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector & packedShortestPath) { + inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector & packedShortestPath) { std::vector packedAlternativePath; super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath); @@ -270,8 +309,8 @@ private: //compute forward sharing while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) { // INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")"); - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); - sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); + sharing += search_graph->GetEdgeData(edgeID).distance; ++aindex; } @@ -279,55 +318,65 @@ private: int bindex = packedShortestPath.size()-1; //compute backward sharing while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]); - sharing += super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]); + sharing += search_graph->GetEdgeData(edgeID).distance; --aindex; --bindex; } return sharing; } - inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector& searchSpaceIntersection) const { - const NodeID node = _forwardHeap->DeleteMin(); + template + inline void AlternativeRoutingStep( + QueryHeap & _forward_heap, + QueryHeap & _reverse_heap, + NodeID *middle_node, + int *upper_bound_to_shortest_path_distance, + std::vector& searchSpaceIntersection, + std::vector & search_space, + const int edgeBasedOffset + ) const { + const NodeID node = _forward_heap.DeleteMin(); + const int distance = _forward_heap.GetKey(node); + int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); + if(scaledDistance > *upper_bound_to_shortest_path_distance){ + _forward_heap.DeleteAll(); + return; + } - const int distance = _forwardHeap->GetKey(node); - if(_backwardHeap->WasInserted(node) ){ + search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node)); + + if(_reverse_heap.WasInserted(node) ){ searchSpaceIntersection.push_back(node); - const int newDistance = _backwardHeap->GetKey(node) + distance; - if(newDistance < *_upperbound ){ + const int newDistance = _reverse_heap.GetKey(node) + distance; + if(newDistance < *upper_bound_to_shortest_path_distance ){ if(newDistance>=0 ) { - *middle = node; - *_upperbound = newDistance; + *middle_node = node; + *upper_bound_to_shortest_path_distance = newDistance; } } } - int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); - if(scaledDistance > *_upperbound){ - _forwardHeap->DeleteAll(); - return; - } - - for ( typename QueryDataT::Graph::EdgeIterator edge = super::_queryData.graph->BeginEdges( node ); edge < super::_queryData.graph->EndEdges(node); edge++ ) { - const typename QueryDataT::Graph::EdgeData & data = super::_queryData.graph->GetEdgeData(edge); + for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) { + const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); if(forwardDirectionFlag) { - const NodeID to = super::_queryData.graph->GetTarget(edge); + const NodeID to = search_graph->GetTarget(edge); const int edgeWeight = data.distance; assert( edgeWeight > 0 ); const int toDistance = distance + edgeWeight; //New Node discovered -> Add to Heap + Node Info Storage - if ( !_forwardHeap->WasInserted( to ) ) { - _forwardHeap->Insert( to, toDistance, node ); + if ( !_forward_heap.WasInserted( to ) ) { + _forward_heap.Insert( to, toDistance, node ); } //Found a shorter Path -> Update distance - else if ( toDistance < _forwardHeap->GetKey( to ) ) { - _forwardHeap->GetData( to ).parent = node; - _forwardHeap->DecreaseKey( to, toDistance ); + else if ( toDistance < _forward_heap.GetKey( to ) ) { + _forward_heap.GetData( to ).parent = node; + _forward_heap.DecreaseKey( to, toDistance ); //new parent } } @@ -335,16 +384,17 @@ private: } //conduct T-Test - inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { + inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { + newForwardHeap.Clear(); + newBackwardHeap.Clear(); std::vector < NodeID > packed_s_v_path; std::vector < NodeID > packed_v_t_path; - super::_queryData.InitializeOrClearSecondThreadLocalStorage(); *s_v_middle = UINT_MAX; int upperBoundFor_s_v_Path = INT_MAX; //compute path by reusing forward search from s - newBackwardHeap->Insert(candidate.node, 0, candidate.node); - while (newBackwardHeap->Size() > 0) { + newBackwardHeap.Insert(candidate.node, 0, candidate.node); + while (newBackwardHeap.Size() > 0) { super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false); } @@ -354,8 +404,8 @@ private: //compute path by reusing backward search from t *v_t_middle = UINT_MAX; int upperBoundFor_v_t_Path = INT_MAX; - newForwardHeap->Insert(candidate.node, 0, candidate.node); - while (newForwardHeap->Size() > 0) { + newForwardHeap.Insert(candidate.node, 0, candidate.node); + while (newForwardHeap.Size() > 0) { super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true); } @@ -372,11 +422,11 @@ private: const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath; int unpackedUntilDistance = 0; - std::stack unpackStack; + std::stack unpackStack; //Traverse path s-->v for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); - int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); + int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance; if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i])); } else { @@ -386,17 +436,17 @@ private: } while (!unpackStack.empty()) { - const UnpackEdge viaPathEdge = unpackStack.top(); + const SearchSpaceEdge viaPathEdge = unpackStack.top(); unpackStack.pop(); - typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); + typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); if(UINT_MAX == edgeIDInViaPath) return false; - typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath); + typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath); bool IsViaEdgeShortCut = currentEdgeData.shortcut; if (IsViaEdgeShortCut) { const NodeID middleOfViaPath = currentEdgeData.id; - typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); - int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).distance; + typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); + int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance; //attention: !unpacking in reverse! //Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one. if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) { @@ -416,8 +466,8 @@ private: unpackedUntilDistance = 0; //Traverse path s-->v for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) { - typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]); - int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance; + typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]); + int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance; if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1])); } else { @@ -427,17 +477,17 @@ private: } while (!unpackStack.empty()) { - const UnpackEdge viaPathEdge = unpackStack.top(); + const SearchSpaceEdge viaPathEdge = unpackStack.top(); unpackStack.pop(); - typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); + typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); if(UINT_MAX == edgeIDInViaPath) return false; - typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath); + typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath); const bool IsViaEdgeShortCut = currentEdgeData.shortcut; if (IsViaEdgeShortCut) { const NodeID middleOfViaPath = currentEdgeData.id; - typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); - int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance; + typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); + int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance; //Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one. if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) { unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath)); @@ -454,19 +504,18 @@ private: lengthOfPathT_Test_Path += unpackedUntilDistance; //Run actual T-Test query and compare if distances equal. - HeapPtr& forwardHeap = super::_queryData.forwardHeap3; - HeapPtr& backwardHeap = super::_queryData.backwardHeap3; - super::_queryData.InitializeOrClearThirdThreadLocalStorage(); + QueryHeap& forwardHeap = *super::_queryData.forwardHeap3; + QueryHeap& backwardHeap = *super::_queryData.backwardHeap3; int _upperBound = INT_MAX; NodeID middle = UINT_MAX; - forwardHeap->Insert(s_P, 0, s_P); - backwardHeap->Insert(t_P, 0, t_P); + forwardHeap.Insert(s_P, 0, s_P); + backwardHeap.Insert(t_P, 0, t_P); //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while (forwardHeap->Size() + backwardHeap->Size() > 0) { - if (forwardHeap->Size() > 0) { + while (forwardHeap.Size() + backwardHeap.Size() > 0) { + if (forwardHeap.Size() > 0) { super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true); } - if (backwardHeap->Size() > 0) { + if (backwardHeap.Size() > 0) { super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false); } } diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index bbe0474e4..f329c697b 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -23,43 +23,43 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef BASICROUTINGINTERFACE_H_ #define BASICROUTINGINTERFACE_H_ +#include + #include #include #include "../Plugins/RawRouteData.h" +#include "../Util/ContainerUtils.h" template -class BasicRoutingInterface { +class BasicRoutingInterface : boost::noncopyable{ protected: QueryDataT & _queryData; public: BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { } virtual ~BasicRoutingInterface(){ }; - inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const { - const NodeID node = _forwardHeap->DeleteMin(); - const int distance = _forwardHeap->GetKey(node); -// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance); - if(_backwardHeap->WasInserted(node) ){ -// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound); - const int newDistance = _backwardHeap->GetKey(node) + distance; + inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const { + const NodeID node = _forwardHeap.DeleteMin(); + const int distance = _forwardHeap.GetKey(node); + if(_backwardHeap.WasInserted(node) ){ + const int newDistance = _backwardHeap.GetKey(node) + distance; if(newDistance < *_upperbound ){ if(newDistance>=0 ) { -// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance); *middle = node; *_upperbound = newDistance; } else { -// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance); } } } if(distance-edgeBasedOffset > *_upperbound){ - _forwardHeap->DeleteAll(); + _forwardHeap.DeleteAll(); return; } - for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) { + //Stalling + for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) { const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge); bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward; if(backwardDirectionFlag) { @@ -68,16 +68,15 @@ public: assert( edgeWeight > 0 ); - //Stalling - if(_forwardHeap->WasInserted( to )) { - if(_forwardHeap->GetKey( to ) + edgeWeight < distance) { + if(_forwardHeap.WasInserted( to )) { + if(_forwardHeap.GetKey( to ) + edgeWeight < distance) { return; } } } } - for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) { + for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) { const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge); bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); if(forwardDirectionFlag) { @@ -89,23 +88,20 @@ public: const int toDistance = distance + edgeWeight; //New Node discovered -> Add to Heap + Node Info Storage - if ( !_forwardHeap->WasInserted( to ) ) { - // INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance); - _forwardHeap->Insert( to, toDistance, node ); + if ( !_forwardHeap.WasInserted( to ) ) { + _forwardHeap.Insert( to, toDistance, node ); } //Found a shorter Path -> Update distance - else if ( toDistance < _forwardHeap->GetKey( to ) ) { - // INFO((forwardDirection ? "[forw]" : "[back]") << " decrease and scanning edge (" << node << "," << to << ") from " << _forwardHeap->GetKey(to) << "to " << toDistance << ", edge length: " << data.distance); - _forwardHeap->GetData( to ).parent = node; - _forwardHeap->DecreaseKey( to, toDistance ); + else if ( toDistance < _forwardHeap.GetKey( to ) ) { + _forwardHeap.GetData( to ).parent = node; + _forwardHeap.DecreaseKey( to, toDistance ); //new parent } } } } - inline void UnpackPath(std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { - + inline void UnpackPath(const std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { const unsigned sizeOfPackedPath = packedPath.size(); std::stack > recursionStack; @@ -118,15 +114,12 @@ public: while(!recursionStack.empty()) { edge = recursionStack.top(); recursionStack.pop(); -// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")"); typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID; int smallestWeight = INT_MAX; for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){ const int weight = _queryData.graph->GetEdgeData(eit).distance; -// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")"); if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){ -// INFO("1smallest " << eit << ", " << weight); smallestEdge = eit; smallestWeight = weight; } @@ -135,9 +128,7 @@ public: if(smallestEdge == SPECIAL_EDGEID){ for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){ const int weight = _queryData.graph->GetEdgeData(eit).distance; -// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")"); if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){ -// INFO("2smallest " << eit << ", " << weight); smallestEdge = eit; smallestWeight = weight; } @@ -159,7 +150,6 @@ public: } inline void UnpackEdge(const NodeID s, const NodeID t, std::vector & unpackedPath) const { - std::stack > recursionStack; recursionStack.push(std::make_pair(s,t)); @@ -193,7 +183,6 @@ public: if(ed.shortcut) {//unpack const NodeID middle = ed.id; //again, we need to this in reversed order -// INFO("unpacking (" << middle << "," << edge.second << ") and (" << edge.first << "," << middle << ")"); recursionStack.push(std::make_pair(middle, edge.second)); recursionStack.push(std::make_pair(edge.first, middle)); } else { @@ -204,22 +193,29 @@ public: unpackedPath.push_back(t); } - inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector& packedPath) { + inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector& packedPath) const { NodeID pathNode = middle; - while(pathNode != _fHeap->GetData(pathNode).parent) { - pathNode = _fHeap->GetData(pathNode).parent; + while(pathNode != _fHeap.GetData(pathNode).parent) { + pathNode = _fHeap.GetData(pathNode).parent; packedPath.push_back(pathNode); } std::reverse(packedPath.begin(), packedPath.end()); - packedPath.push_back(middle); pathNode = middle; - while (pathNode != _bHeap->GetData(pathNode).parent){ - pathNode = _bHeap->GetData(pathNode).parent; + while (pathNode != _bHeap.GetData(pathNode).parent){ + pathNode = _bHeap.GetData(pathNode).parent; packedPath.push_back(pathNode); } } + + inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector& packed_path) const { + NodeID pathNode = middle; + while(pathNode != search_heap.GetData(pathNode).parent) { + pathNode = search_heap.GetData(pathNode).parent; + packed_path.push_back(pathNode); + } + } }; diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index 6fc4c5996..a21673807 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -28,13 +28,14 @@ or see http://www.gnu.org/licenses/agpl.txt. template class ShortestPathRouting : public BasicRoutingInterface{ typedef BasicRoutingInterface super; + typedef typename QueryDataT::QueryHeap QueryHeap; public: - ShortestPathRouting(QueryDataT & qd) : super(qd) {} + ShortestPathRouting( QueryDataT & qd) : super(qd) {} ~ShortestPathRouting() {} - void operator()(std::vector & phantomNodesVector, RawRouteData & rawRouteData) { - BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { + void operator()(std::vector & phantomNodesVector, RawRouteData & rawRouteData) const { + BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) { if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) { rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX; return; @@ -43,77 +44,65 @@ public: int distance1 = 0; int distance2 = 0; - bool searchFrom1stStartNode(true); - bool searchFrom2ndStartNode(true); - NodeID middle1 = ( NodeID ) UINT_MAX; - NodeID middle2 = ( NodeID ) UINT_MAX; + bool searchFrom1stStartNode = true; + bool searchFrom2ndStartNode = true; + NodeID middle1 = UINT_MAX; + NodeID middle2 = UINT_MAX; std::vector packedPath1; std::vector packedPath2; - typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap; - typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap; - - typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2; - typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2; + super::_queryData.InitializeOrClearFirstThreadLocalStorage(); + super::_queryData.InitializeOrClearSecondThreadLocalStorage(); + QueryHeap & forwardHeap = *super::_queryData.forwardHeap; + QueryHeap & backwardHeap = *super::_queryData.backwardHeap; + QueryHeap & forwardHeap2 = *super::_queryData.forwardHeap2; + QueryHeap & backwardHeap2 = *super::_queryData.backwardHeap2; //Get distance to next pair of target nodes. - BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) { - super::_queryData.InitializeOrClearFirstThreadLocalStorage(); - super::_queryData.InitializeOrClearSecondThreadLocalStorage(); - + BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) { + forwardHeap.Clear(); forwardHeap2.Clear(); + backwardHeap.Clear(); backwardHeap2.Clear(); int _localUpperbound1 = INT_MAX; int _localUpperbound2 = INT_MAX; //insert new starting nodes into forward heap, adjusted by previous distances. if(searchFrom1stStartNode) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); - forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); -// INFO("a 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1); -// } else { -// INFO("Skipping first start node"); + forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); } if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) { - forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); - forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); -// INFO("b 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << -phantomNodePair.startPhantom.weight1); -// } else if(!searchFrom2ndStartNode) { -// INFO("Skipping second start node"); + forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); } -// backwardHeap->Clear(); -// backwardHeap2->Clear(); //insert new backward nodes into backward heap, unadjusted. - backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); -// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1); + backwardHeap.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); if(phantomNodePair.targetPhantom.isBidirected() ) { -// INFO("2) back insert " << phantomNodePair.targetPhantom.edgeBasedNode+1 << " with weight " << phantomNodePair.targetPhantom.weight2); - backwardHeap2->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); + backwardHeap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ; offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ; //run two-Target Dijkstra routing step. - while(forwardHeap->Size() + backwardHeap->Size() > 0){ - if(forwardHeap->Size() > 0){ + while(forwardHeap.Size() + backwardHeap.Size() > 0){ + if(forwardHeap.Size() > 0){ super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true); } - if(backwardHeap->Size() > 0){ + if(backwardHeap.Size() > 0){ super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false); } } - if(backwardHeap2->Size() > 0) { - while(forwardHeap2->Size() + backwardHeap2->Size() > 0){ - if(forwardHeap2->Size() > 0){ + if(backwardHeap2.Size() > 0) { + while(forwardHeap2.Size() + backwardHeap2.Size() > 0){ + if(forwardHeap2.Size() > 0){ super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true); } - if(backwardHeap2->Size() > 0){ + if(backwardHeap2.Size() > 0){ super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false); } } } -// INFO("upperbound1: " << _localUpperbound1 << ", distance1: " << distance1); -// INFO("upperbound2: " << _localUpperbound2 << ", distance2: " << distance2); //No path found for both target nodes? if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) { @@ -122,46 +111,35 @@ public: } if(UINT_MAX == middle1) { searchFrom1stStartNode = false; -// INFO("Next Search will not start from 1st"); } else { -// INFO("Next Search will start from 1st"); searchFrom1stStartNode = true; } if(UINT_MAX == middle2) { searchFrom2ndStartNode = false; -// INFO("Next Search will not start from 2nd"); } else { searchFrom2ndStartNode = true; -// INFO("Next Search will start from 2nd"); } //Was at most one of the two paths not found? assert(!(INT_MAX == distance1 && INT_MAX == distance2)); -// INFO("middle1: " << middle1); - //Unpack paths if they exist std::vector temporaryPackedPath1; std::vector temporaryPackedPath2; if(INT_MAX != _localUpperbound1) { super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1); -// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) ); } -// INFO("middle2: " << middle2); if(INT_MAX != _localUpperbound2) { super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2); -// INFO("temporaryPackedPath2 ends with " << *(temporaryPackedPath2.end()-1) ); } //if one of the paths was not found, replace it with the other one. if(0 == temporaryPackedPath1.size()) { -// INFO("Deleting path 1"); temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); _localUpperbound1 = _localUpperbound2; } if(0 == temporaryPackedPath2.size()) { -// INFO("Deleting path 2"); temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end()); _localUpperbound2 = _localUpperbound1; } @@ -170,28 +148,21 @@ public: //Plug paths together, s.t. end of packed path is begin of temporary packed path if(0 < packedPath1.size() && 0 < packedPath2.size() ) { -// INFO("Both paths are non-empty"); if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) { -// INFO("both paths start with the same node:" << *(temporaryPackedPath1.begin())); //both new route segments start with the same node, thus one of the packedPath must go. assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) ); if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) { -// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1)); packedPath2.clear(); packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end()); distance2 = distance1; -// INFO("packedPath2 now ends with " << *(packedPath2.end()-1)); } else { -// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1)); packedPath1.clear(); packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end()); distance1 = distance2; -// INFO("Path1 now ends with " << *(packedPath1.end()-1)); } } else { //packed paths 1 and 2 may need to switch. if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) { -// INFO("Switching"); packedPath1.swap(packedPath2); std::swap(distance1, distance2); } @@ -201,61 +172,24 @@ public: packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end()); if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) { -// INFO("both paths end in same direction on bidirected edge, make sure start only start with : " << packedPath1.back()); NodeID lastNodeID = packedPath2.back(); searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1); searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode); -// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode << ": " << (searchFrom1stStartNode ? "yes" : "no") ); -// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ": " << (searchFrom2ndStartNode ? "yes" : "no") ); } distance1 += _localUpperbound1; distance2 += _localUpperbound2; } -// INFO("length path1: " << distance1); -// INFO("length path2: " << distance2); - if(distance1 <= distance2){ - //remove consecutive duplicates -// std::cout << "unclean 1: "; -// for(unsigned i = 0; i < packedPath1.size(); ++i) -// std::cout << packedPath1[i] << " "; -// std::cout << std::endl; - -// std::cout << "cleaned 1: "; -// for(unsigned i = 0; i < packedPath1.size(); ++i) -// std::cout << packedPath1[i] << " "; -// std::cout << std::endl; -// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath); - } else { + if(distance1 > distance2){ std::swap(packedPath1, packedPath2); -// std::cout << "unclean 2: "; -// for(unsigned i = 0; i < packedPath2.size(); ++i) -// std::cout << packedPath2[i] << " "; -// std::cout << std::endl; -// _RemoveConsecutiveDuplicatesFromContainer(packedPath2); -// std::cout << "cleaned 2: "; -// for(unsigned i = 0; i < packedPath2.size(); ++i) -// std::cout << packedPath2[i] << " "; -// std::cout << std::endl; -// super::UnpackPath(packedPath2, unpackedPath); } - _RemoveConsecutiveDuplicatesFromContainer(packedPath1); + remove_consecutive_duplicates_from_vector(packedPath1); super::UnpackPath(packedPath1, rawRouteData.computedShortestPath); rawRouteData.lengthOfShortestPath = std::min(distance1, distance2); -// INFO("Found via route with distance " << std::min(distance1, distance2)); return; } -private: - template - void _RemoveConsecutiveDuplicatesFromContainer(ContainerT & packedPath) { - //remove consecutive duplicates - typename ContainerT::iterator it; - // using default comparison: - it = std::unique(packedPath.begin(), packedPath.end()); - packedPath.resize(it - packedPath.begin()); - } }; #endif /* SHORTESTPATHROUTING_H_ */ From 9ffcaa55507ab5377eca2c38db02fd6152e48f1a Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 16:56:59 +0100 Subject: [PATCH 105/161] Fixed offset, moved rvalues to the left in comparisons and const'ed a few things. --- RoutingAlgorithms/ShortestPathRouting.h | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index a21673807..4799d49d3 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -81,31 +81,31 @@ public: if(phantomNodePair.targetPhantom.isBidirected() ) { backwardHeap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } - int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ; - offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ; + const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0); + const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0); //run two-Target Dijkstra routing step. - while(forwardHeap.Size() + backwardHeap.Size() > 0){ - if(forwardHeap.Size() > 0){ - super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true); + while(0 < (forwardHeap.Size() + backwardHeap.Size() )){ + if(0 < forwardHeap.Size()){ + super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, forward_offset, true); } - if(backwardHeap.Size() > 0){ - super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false); + if(0 < backwardHeap.Size() ){ + super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, reverse_offset, false); } } - if(backwardHeap2.Size() > 0) { - while(forwardHeap2.Size() + backwardHeap2.Size() > 0){ - if(forwardHeap2.Size() > 0){ - super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true); + if(0 < backwardHeap2.Size()) { + while(0 < (forwardHeap2.Size() + backwardHeap2.Size() )){ + if(0 < forwardHeap2.Size()){ + super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, forward_offset, true); } - if(backwardHeap2.Size() > 0){ - super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false); + if(0 < backwardHeap2.Size()){ + super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, reverse_offset, false); } } } //No path found for both target nodes? - if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) { + if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) { rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX; return; } From 961a379f79caeb9d3a9271e17c4a122d9c01afb5 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 17:07:31 +0100 Subject: [PATCH 106/161] Fixing signed/unsigned comparison warnings --- Descriptors/JSONDescriptor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 5cd24877b..72a011b55 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -264,7 +264,7 @@ public: std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) ); int size_of_difference = shortestDifference.size(); if(0 < size_of_difference ) { - unsigned i = 0; + int i = 0; while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) { ++i; } @@ -276,7 +276,7 @@ public: std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) ); size_of_difference = alternativeDifference.size(); if(0 < size_of_difference ) { - unsigned i = 0; + int i = 0; while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) { ++i; } From 7544727f7acf7da9304c60f7edb90bb40e2a209c Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 17:08:15 +0100 Subject: [PATCH 107/161] Turn on all warnings during build by default --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 2f09e53aa..83e70de89 100644 --- a/SConstruct +++ b/SConstruct @@ -87,7 +87,7 @@ if "clang" in env["CXX"]: if GetOption('allflags') is not None: env.Append(CXXFLAGS = ["-W#warnings", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"]) else: - env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp']) + env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp', '-Wall']) env.Append(LINKFLAGS = '-fopenmp') if GetOption('buildconfiguration') == 'debug': From 73c81a0a6c9712e5f705f8eb9908ee9fe03f58b3 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 18:13:57 +0100 Subject: [PATCH 108/161] Removing debug output --- Contractor/EdgeBasedGraphFactory.cpp | 1 - features/bicycle/maxspeed.feature | 5 +---- features/car/maxspeed.feature | 9 +++------ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 5aaacb859..0dada46ae 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -376,7 +376,6 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID return TurnInstructions.NoTurn; } if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) { - ERR("should not happen"); return TurnInstructions.NoTurn; } diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 9ca10006b..892daeba4 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -34,10 +34,7 @@ Feature: Bike - Max speed restrictions @todo Scenario: Bike - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | f | g | h | - - And the shortcuts + Given the shortcuts | key | value | | bike | 43s ~10% | | run | 73s ~10% | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 55de6bd8a..f0d038724 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -35,17 +35,14 @@ Feature: Car - Max speed restrictions @todo Scenario: Car - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | f | g | h | - - And a grid size of 100 meters - - And the shortcuts + Given the shortcuts | key | value | | car | 12s ~10% | | run | 73s ~10% | | walk | 170s ~10% | | snail | 720s ~10% | + + And a grid size of 100 meters Then routability should be | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | From 034ce137a9f0de25be25b36088507b9684ab8f3e Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 18:15:39 +0100 Subject: [PATCH 109/161] removing file --- profile.lua | 209 ---------------------------------------------------- 1 file changed, 209 deletions(-) delete mode 100644 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 100644 index c078647f6..000000000 --- a/profile.lua +++ /dev/null @@ -1,209 +0,0 @@ --- Begin of globals -require("lib/access") - -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = 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 } -access_tag_restricted = { ["destination"] = true, ["delivery"] = true } -access_tags = { "motorcar", "motor_vehicle", "vehicle" } -access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } -service_tag_restricted = { ["parking_aisle"] = true } -ignore_in_grid = { ["ferry"] = true } -restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } - -speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, --- ["track"] = 5, - ["ferry"] = 5, - ["default"] = 50 -} - -take_minimum_of_speeds = false -obey_oneway = true -obey_bollards = true -use_restrictions = true -ignore_areas = true -- future feature -traffic_signal_penalty = 2 -u_turn_penalty = 20 - --- End of globals - -function get_exceptions(vector) - for i,v in ipairs(restriction_exception_tags) do - vector:Add(v) - end -end - -local function parse_maxspeed(source) - if source == nil then - return 0 - end - local n = tonumber(source:match("%d*")) - if n == nil then - n = 0 - end - if string.match(source, "mph") or string.match(source, "mp/h") then - n = (n*1609)/1000; - end - return math.abs(n) -end - -function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; - end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end - end - return 1 -end - - -function way_function (way, numberOfNodesInWay) - - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name --- else --- way.name = highway -- if no name exists, use way type - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) - then - if durationIsValid(duration) then - way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ); - way.is_duration_set = true - end - way.direction = Way.bidirectional - if speed_profile[route] ~= nil then - highway = route; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) - end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end - - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end - - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel - - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 - return 1 -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 From 305ce042843384652ee8c185858456185aa929a4 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 3 Feb 2013 18:16:36 +0100 Subject: [PATCH 110/161] replacing by symlink --- profile.lua | 1 + 1 file changed, 1 insertion(+) create mode 120000 profile.lua diff --git a/profile.lua b/profile.lua new file mode 120000 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file From c65fed1d387eafd5ba220f49f70806c5e8357d8d Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 18:23:23 +0100 Subject: [PATCH 111/161] simplify testbot maxspeed forw/back test --- features/testbot/maxspeed.feature | 38 ++++++++----------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature index bd9a56987..c6b210e48 100644 --- a/features/testbot/maxspeed.feature +++ b/features/testbot/maxspeed.feature @@ -41,32 +41,12 @@ Feature: Car - Max speed restrictions @opposite Scenario: Testbot - Forward/backward maxspeed - Given the node map - | a | b | c | d | e | f | g | h | - - And the ways - | nodes | maxspeed | maxspeed:forward | maxspeed:backward | - | ab | | | | - | bc | 18 | | | - | cd | | 18 | | - | de | | | 18 | - | ef | 9 | 18 | | - | fg | 9 | | 18 | - | gh | 9 | 24 | 18 | - - When I route I should get - | from | to | route | time | - | a | b | ab | 10s +-1 | - | b | a | ab | 10s +-1 | - | b | c | bc | 20s +-1 | - | c | b | bc | 20s +-1 | - | c | d | cd | 20s +-1 | - | d | c | cd | 10s +-1 | - | d | e | de | 10s +-1 | - | e | d | de | 20s +-1 | - | e | f | ef | 20s +-1 | - | f | e | ef | 40s +-1 | - | f | g | fg | 40s +-1 | - | g | f | fg | 20s +-1 | - | g | h | gh | 15s +-1 | - | h | g | gh | 20s +-1 | + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | 20s +-1 | 20s +-1 | + | 18 | | | 40s +-1 | 40s +-1 | + | | 18 | | 40s +-1 | 20s +-1 | + | | | 18 | 20s +-1 | 40s +-1 | + | 9 | 18 | | 40s +-1 | 80s +-1 | + | 9 | | 18 | 80s +-1 | 40s +-1 | + | 9 | 24 | 18 | 30s +-1 | 40s +-1 | \ No newline at end of file From ccdd0f599a74b222a6fd9e6aaea6a9a9687cf959 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 20:17:06 +0100 Subject: [PATCH 112/161] test nearest API --- features/nearest/pick.feature | 34 +++++++++ features/nearest/projection.feature | 105 +++++++++++++++++++++++++++ features/step_definitions/nearest.rb | 51 +++++++++++++ features/support/fuzzy.rb | 32 ++++++++ features/support/nearest.rb | 17 +++++ 5 files changed, 239 insertions(+) create mode 100644 features/nearest/pick.feature create mode 100644 features/nearest/projection.feature create mode 100644 features/step_definitions/nearest.rb create mode 100644 features/support/fuzzy.rb create mode 100644 features/support/nearest.rb diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature new file mode 100644 index 000000000..4c8284293 --- /dev/null +++ b/features/nearest/pick.feature @@ -0,0 +1,34 @@ +@nearest +Feature: Locating Nearest node on a Way - pick closest way + + Background: + Given the profile "testbot" + + @todo + Scenario: Nearest - two ways crossing + Given the node map + | | 0 | c | 1 | | + | 7 | | n | | 2 | + | a | k | x | m | b | + | 6 | | l | | 3 | + | | 5 | d | 4 | | + + And the ways + | nodes | + | axc | + | cxd | + + When I request nearest I should get + | in | out | + | 0 | c | + | 1 | c | + | 2 | b | + | 3 | b | + | 4 | d | + | 5 | d | + | 6 | a | + | 7 | a | + | k | k | + | l | l | + | m | m | + | n | n | diff --git a/features/nearest/projection.feature b/features/nearest/projection.feature new file mode 100644 index 000000000..f33a19f81 --- /dev/null +++ b/features/nearest/projection.feature @@ -0,0 +1,105 @@ +@nearest +Feature: Locating Nearest node on a Way - basic projection onto way + + Background: + Given the profile "testbot" + + Scenario: Nearest - easy-west way + Given the node map + | 0 | 1 | 2 | 3 | 4 | + | | a | x | b | | + | 5 | 6 | 7 | 8 | 9 | + + And the ways + | nodes | + | ab | + + When I request nearest I should get + | in | out | + | 0 | a | + | 1 | a | + | 2 | x | + | 3 | b | + | 4 | b | + | 5 | a | + | 6 | a | + | 7 | x | + | 8 | b | + | 9 | b | + + Scenario: Nearest - north-south way + Given the node map + | 0 | | 5 | + | 1 | a | 6 | + | 2 | x | 7 | + | 3 | b | 8 | + | 4 | | 9 | + + And the ways + | nodes | + | ab | + + When I request nearest I should get + | in | out | + | 0 | a | + | 1 | a | + | 2 | x | + | 3 | b | + | 4 | b | + | 5 | a | + | 6 | a | + | 7 | x | + | 8 | b | + | 9 | b | + + Scenario: Nearest - diagonal 1 + Given the node map + | 8 | | 4 | | | | + | | a | | 5 | | | + | 0 | | x | | 6 | | + | | 1 | | y | | 7 | + | | | 2 | | b | | + | | | | 3 | | 9 | + + And the ways + | nodes | + | ab | + + When I request nearest I should get + | in | out | + | 0 | a | + | 1 | x | + | 2 | y | + | 3 | b | + | 4 | a | + | 5 | x | + | 6 | y | + | 7 | b | + | 8 | a | + | 9 | b | + + Scenario: Nearest - diagonal 2 + Given the node map + | | | | 3 | | 9 | + | | | 2 | | b | | + | | 1 | | y | | 7 | + | 0 | | x | | 6 | | + | | a | | 5 | | | + | 8 | | 4 | | | | + + And the ways + | nodes | + | ab | + + When I request nearest I should get + | in | out | + | 0 | a | + | 1 | x | + | 2 | y | + | 3 | b | + | 4 | a | + | 5 | x | + | 6 | y | + | 7 | b | + | 8 | a | + | 9 | b | diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb new file mode 100644 index 000000000..303788b47 --- /dev/null +++ b/features/step_definitions/nearest.rb @@ -0,0 +1,51 @@ +When /^I request nearest I should get$/ do |table| + reprocess + actual = [] + OSRMLauncher.new do + table.hashes.each_with_index do |row,ri| + in_node = @name_node_hash[ row['in'] ] + raise "*** unknown in-node '#{row['in']}" unless in_node + + out_node = @name_node_hash[ row['out'] ] + raise "*** unknown out-node '#{row['out']}" unless out_node + + response = request_nearest("#{in_node.lat},#{in_node.lon}") + if response.code == "200" && response.body.empty? == false + json = JSON.parse response.body + if json['status'] == 0 + coord = json['mapped_coordinate'] + end + end + + got = {'in' => row['in'], 'out' => coord } + + ok = true + row.keys.each do |key| + if key=='out' + if FuzzyMatch.match_location coord, out_node + got[key] = row[key] + else + row[key] = "#{row[key]} [#{out_node.lat},#{out_node.lon}]" + ok = false + end + end + end + + unless ok + failed = { :attempt => 'nearest', :query => @query, :response => response } + log_fail row,got,[failed] + end + + actual << got + end + end + table.routing_diff! actual +end + +When /^I route (\d+) times I should get$/ do |n,table| + ok = true + n.to_i.times do + ok = false unless step "I route I should get", table + end + ok +end \ No newline at end of file diff --git a/features/support/fuzzy.rb b/features/support/fuzzy.rb new file mode 100644 index 000000000..0876f9f66 --- /dev/null +++ b/features/support/fuzzy.rb @@ -0,0 +1,32 @@ + +class FuzzyMatch + + def self.match got, want + if got == want + return true + elsif want.match /(.*)\s+~(.+)%$/ #percentage range: 100 ~5% + margin = 1 - $2.to_f*0.01 + from = $1.to_f*margin + to = $1.to_f/margin + return got.to_f >= from && got.to_f <= to + elsif want.match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5 + margin = $2.to_f + from = $1.to_f-margin + to = $1.to_f+margin + return got.to_f >= from && got.to_f <= to + elsif want =~ /^\/(.*)\/$/ #regex: /a,b,.*/ + return got =~ /#{$1}/ + else + return false + end + end + + def self.match_location got, want + match( got[0], "#{want.lat} ~0.002%" ) && + match( got[1], "#{want.lon} ~0.002%" ) + end + +end + + + diff --git a/features/support/nearest.rb b/features/support/nearest.rb new file mode 100644 index 000000000..e37130735 --- /dev/null +++ b/features/support/nearest.rb @@ -0,0 +1,17 @@ +require 'net/http' + +def request_nearest_url path + @query = path + uri = URI.parse "#{HOST}/#{path}" + Timeout.timeout(REQUEST_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." +end + +def request_nearest a + request_nearest_url "nearest?loc=#{a}" +end From 76decf2e8b1e01330d93ba10480775f8b05b2933 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 20:24:46 +0100 Subject: [PATCH 113/161] fix nearest test --- features/nearest/pick.feature | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature index 4c8284293..a38c41984 100644 --- a/features/nearest/pick.feature +++ b/features/nearest/pick.feature @@ -4,7 +4,6 @@ Feature: Locating Nearest node on a Way - pick closest way Background: Given the profile "testbot" - @todo Scenario: Nearest - two ways crossing Given the node map | | 0 | c | 1 | | @@ -15,7 +14,7 @@ Feature: Locating Nearest node on a Way - pick closest way And the ways | nodes | - | axc | + | axb | | cxd | When I request nearest I should get From 436cc692da4b97e19d96a06229928deba2fc0cf3 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 20:37:22 +0100 Subject: [PATCH 114/161] a few more test for nearest api --- features/nearest/pick.feature | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature index a38c41984..901e96e8f 100644 --- a/features/nearest/pick.feature +++ b/features/nearest/pick.feature @@ -31,3 +31,43 @@ Feature: Locating Nearest node on a Way - pick closest way | l | l | | m | m | | n | n | + + Scenario: Nearest - inside a triangle + Given the node map + | | | | | | c | | | | | | + | | | | | | | | | | | | + | | | | y | | | | z | | | | + | | | | | 0 | | 1 | | | | | + | | | | 2 | | 3 | | 4 | | | | + | a | | | x | | u | | w | | | b | + + And the ways + | nodes | + | ab | + | bc | + | ca | + + When I request nearest I should get + | in | out | + | 0 | y | + | 1 | z | + | 2 | x | + | 3 | u | + | 4 | w | + + Scenario: Nearest - only pick routable ways + Given the node map + | | a | c | e | | + | 0 | z | y | x | 1 | + | | b | d | f | | + + And the ways + | nodes | highway | barrier | + | ab | | wall | + | cd | (nil) | | + | ef | primary | | + + When I request nearest I should get + | in | out | + | 0 | z | + | 1 | x | From bb1064ac421155d50c276f1f8d51955d7f9e379c Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 3 Feb 2013 21:01:10 +0100 Subject: [PATCH 115/161] remove a nearest test, for now --- features/nearest/pick.feature | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/features/nearest/pick.feature b/features/nearest/pick.feature index 901e96e8f..f3bd76d76 100644 --- a/features/nearest/pick.feature +++ b/features/nearest/pick.feature @@ -53,21 +53,4 @@ Feature: Locating Nearest node on a Way - pick closest way | 1 | z | | 2 | x | | 3 | u | - | 4 | w | - - Scenario: Nearest - only pick routable ways - Given the node map - | | a | c | e | | - | 0 | z | y | x | 1 | - | | b | d | f | | - - And the ways - | nodes | highway | barrier | - | ab | | wall | - | cd | (nil) | | - | ef | primary | | - - When I request nearest I should get - | in | out | - | 0 | z | - | 1 | x | + | 4 | w | \ No newline at end of file From d67ac1a7088bfb8f27a8c895605b0cb68f492a23 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 4 Feb 2013 10:31:35 +0100 Subject: [PATCH 116/161] fuzzy matching in routability tables, ported from opposite branch --- features/step_definitions/data.rb | 6 ++++++ features/step_definitions/routability.rb | 7 +++++-- features/step_definitions/routing.rb | 26 +++--------------------- features/support/data.rb | 10 +++++++-- features/support/fuzzy.rb | 2 -- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb index c2cf35c3b..c16adaacb 100644 --- a/features/step_definitions/data.rb +++ b/features/step_definitions/data.rb @@ -6,6 +6,12 @@ Given /^a grid size of (\d+) meters$/ do |meters| set_grid_size meters end +Given /^the shortcuts$/ do |table| + table.hashes.each do |row| + shortcuts_hash[ row['key'] ] = row['value'] + end +end + Given /^the node map$/ do |table| table.raw.each_with_index do |row,ri| row.each_with_index do |name,ci| diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index d949d01b9..0af027a98 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -16,18 +16,21 @@ Then /^routability should be$/ do |table| elsif direction == 'backw' || direction == 'bothw' response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}") end + want = shortcuts_hash[row[direction]] || row[direction] #expand shortcuts got[direction] = route_status response json = JSON.parse(response.body) if got[direction].empty? == false route = way_list json['route_instructions'] if route != "w#{i}" got[direction] = "testing w#{i}, but got #{route}!?" - elsif row[direction] =~ /\d+s/ + elsif want =~ /^\d+s/ time = json['route_summary']['total_time'] got[direction] = "#{time}s" end end - if got[direction] != row[direction] + if FuzzyMatch.match got[direction], want + got[direction] = row[direction] + else attempts << { :attempt => direction, :query => @query, :response => response } end end diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 32e6f60e5..8227c1a75 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -50,30 +50,10 @@ When /^I route I should get$/ do |table| ok = true row.keys.each do |key| - if row[key].match /(.*)\s+~(.+)%$/ #percentage range: 100 ~5% - margin = 1 - $2.to_f*0.01 - from = $1.to_f*margin - to = $1.to_f/margin - if got[key].to_f >= from && got[key].to_f <= to - got[key] = row[key] - else - ok = false - end - elsif row[key].match /(.*)\s+\+\-(.+)$/ #absolute range: 100 +-5 - margin = $2.to_f - from = $1.to_f-margin - to = $1.to_f+margin - if got[key].to_f >= from && got[key].to_f <= to - got[key] = row[key] - else - ok = false - end - elsif row[key] =~ /^\/(.*)\/$/ #regex: /a,b,.*/ - if got[key] =~ /#{$1}/ - got[key] = row[key] - end + if FuzzyMatch.match got[key], row[key] + got[key] = row[key] else - ok = row[key] == got[key] + ok = false end end diff --git a/features/support/data.rb b/features/support/data.rb index f83bbd223..8e2e23f76 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -71,8 +71,14 @@ def build_ways_from_table table way << node5 tags = row.dup - tags.delete 'forw' - tags.delete 'backw' + #remove tags that describe expected test result + tags.reject! do |k,v| + k =~ /^forw\b/ || + k =~ /^backw\b/ || + k =~ /^bothw\b/ + end + + #remove empty tags tags.reject! { |k,v| v=='' } # sort tag keys in the form of 'node/....' diff --git a/features/support/fuzzy.rb b/features/support/fuzzy.rb index 0876f9f66..9138dcce5 100644 --- a/features/support/fuzzy.rb +++ b/features/support/fuzzy.rb @@ -28,5 +28,3 @@ class FuzzyMatch end - - From 97f1dc074928dea6d7fd6d478db7cdf1fb61eb7e Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 4 Feb 2013 11:15:06 +0100 Subject: [PATCH 117/161] update maxspeed tests, remove maxspeed from foot profile --- features/bicycle/maxspeed.feature | 55 +++++++++++++++++-------------- features/car/maxspeed.feature | 52 +++++++++++++++-------------- features/foot/maxspeed.feature | 20 +++++++++++ features/support/shortcuts.rb | 3 ++ profiles/foot.lua | 5 +-- 5 files changed, 82 insertions(+), 53 deletions(-) create mode 100644 features/foot/maxspeed.feature create mode 100644 features/support/shortcuts.rb diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 30d82b7e8..9df5029de 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -3,31 +3,36 @@ Feature: Bike - Max speed restrictions Background: Use specific speeds Given the profile "bicycle" - - Scenario: Bike - Respect maxspeeds when lower that way type speed - Given the node map - | a | b | c | - And the ways - | nodes | highway | maxspeed | - | ab | residential | | - | bc | residential | 10 | + Scenario: Bicycle - Respect maxspeeds when lower that way type speed + Then routability should be + | highway | maxspeed | bothw | + | residential | | 40s ~10% | + | residential | 10 | 72s ~10% | - When I route I should get - | from | to | route | time | - | a | b | ab | 20s ~5% | - | b | c | bc | 36s ~5% | + Scenario: Bicycle - Ignore maxspeed when higher than way speed + Then routability should be + | highway | maxspeed | bothw | + | residential | | 40s ~10% | + | residential | 80 | 40s ~10% | + + @todo + Scenario: Bicycle - Maxspeed formats + Then routability should be + | highway | maxspeed | bothw | + | residential | | 40s ~10% | + | residential | 5 | 144s ~10% | + | residential | 5mph | 90s ~10% | + | residential | 5 mph | 90s ~10% | + | residential | 5MPH | 90s ~10% | + | residential | 5 MPH | 90s ~10% | + | trunk | 5unknown | 40s ~10% | + | trunk | 5 unknown | 40s ~10% | - Scenario: Bike - Do not use maxspeed when higher that way type speed - Given the node map - | a | b | c | - - And the ways - | nodes | highway | maxspeed | - | ab | residential | | - | bc | residential | 80 | - - When I route I should get - | from | to | route | time | - | a | b | ab | 20s ~5% | - | b | c | bc | 20s ~5% | + @todo + Scenario: Bicycle - Maxspeed special tags + Then routability should be + | highway | maxspeed | bothw | + | residential | | 40s ~10% | + | residential | none | 40s ~10% | + | residential | signals | 40s ~10% | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index cc31c6c13..1ca86aaea 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -3,32 +3,36 @@ Feature: Car - Max speed restrictions Background: Use specific speeds Given the profile "car" - Given a grid size of 1000 meters - + Scenario: Car - Respect maxspeeds when lower that way type speed - Given the node map - | a | b | c | - - And the ways - | nodes | highway | maxspeed | - | ab | trunk | | - | bc | trunk | 10 | - - When I route I should get - | from | to | route | time | - | a | b | ab | 42s ~10% | - | b | c | bc | 360s ~10% | + Then routability should be + | highway | maxspeed | bothw | + | trunk | | 9s ~10% | + | trunk | 10 | 72s ~10% | Scenario: Car - Ignore maxspeed when higher than way speed - Given the node map - | a | b | c | + Then routability should be + | highway | maxspeed | bothw | + | residential | | 29s ~10% | + | residential | 85 | 29s ~10% | - And the ways - | nodes | highway | maxspeed | - | ab | residential | | - | bc | residential | 85 | + @todo + Scenario: Car - Maxspeed formats + Then routability should be + | highway | maxspeed | bothw | + | trunk | | 9s ~10% | + | trunk | 10 | 73s ~10% | + | trunk | 10mph | 45s ~10% | + | trunk | 10 mph | 45s ~10% | + | trunk | 10MPH | 45s ~10% | + | trunk | 10 MPH | 45s ~10% | + | trunk | 10unknown | 9s ~10% | + | trunk | 10 unknown | 9s ~10% | - When I route I should get - | from | to | route | time | - | a | b | ab | 144s ~10% | - | b | c | bc | 144s ~10% | + @todo + Scenario: Car - Maxspeed special tags + Then routability should be + | highway | maxspeed | bothw | + | trunk | | 9s ~10% | + | trunk | none | 9s ~10% | + | trunk | signals | 9s ~10% | diff --git a/features/foot/maxspeed.feature b/features/foot/maxspeed.feature new file mode 100644 index 000000000..8a3571a04 --- /dev/null +++ b/features/foot/maxspeed.feature @@ -0,0 +1,20 @@ +@routing @maxspeed @foot +Feature: Foot - Ignore max speed restrictions + +Background: Use specific speeds + Given the profile "foot" + +@todo +Scenario: Foot - Ignore maxspeed + Then routability should be + | highway | maxspeed | bothw | + | residential | | 145s ~10% | + | residential | 1 | 145s ~10% | + | residential | 100 | 145s ~10% | + | residential | 1 | 145s ~10% | + | residential | 1mph | 145s ~10% | + | residential | 1 mph | 145s ~10% | + | residential | 1unknown | 145s ~10% | + | residential | 1 unknown | 145s ~10% | + | residential | none | 145s ~10% | + | residential | signals | 145s ~10% | diff --git a/features/support/shortcuts.rb b/features/support/shortcuts.rb new file mode 100644 index 000000000..20bc3c0fe --- /dev/null +++ b/features/support/shortcuts.rb @@ -0,0 +1,3 @@ +def shortcuts_hash + @shortcuts_hash ||= {} +end diff --git a/profiles/foot.lua b/profiles/foot.lua index 3f689a2d1..e85cc2fd0 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -152,10 +152,7 @@ function way_function (way, numberOfNodesInWay) -- Set the avg speed on the way if it is accessible by road class if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if (0 < maxspeed and not take_minimum_of_speeds) or (maxspeed == 0) then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) + way.speed = speed_profile[highway] end -- Set the avg speed on ways that are marked accessible From 572b17640167b8cdd9a9421e0094954e8e60f4b1 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 4 Feb 2013 12:13:30 +0100 Subject: [PATCH 118/161] Fixes issue #579 --- features/car/maxspeed.feature | 2 +- profiles/car.lua | 319 ++++++++++++++++------------------ 2 files changed, 154 insertions(+), 167 deletions(-) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index cc31c6c13..5b7c66ab0 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -31,4 +31,4 @@ Feature: Car - Max speed restrictions When I route I should get | from | to | route | time | | a | b | ab | 144s ~10% | - | b | c | bc | 144s ~10% | + | b | c | bc | 63s ~10% | diff --git a/profiles/car.lua b/profiles/car.lua index 1a383d1fa..f123dfdfc 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -12,24 +12,24 @@ ignore_in_grid = { ["ferry"] = true } restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, + ["motorway"] = 90, + ["motorway_link"] = 75, + ["trunk"] = 85, + ["trunk_link"] = 70, + ["primary"] = 65, + ["primary_link"] = 60, + ["secondary"] = 55, + ["secondary_link"] = 50, + ["tertiary"] = 40, + ["tertiary_link"] = 30, + ["unclassified"] = 25, + ["residential"] = 25, + ["living_street"] = 10, + ["service"] = 15, -- ["track"] = 5, - ["ferry"] = 5, - ["shuttle_train"] = 10, - ["default"] = 50 + ["ferry"] = 5, + ["shuttle_train"] = 10, + ["default"] = 50 } take_minimum_of_speeds = false @@ -43,171 +43,158 @@ u_turn_penalty = 20 -- End of globals function get_exceptions(vector) - for i,v in ipairs(restriction_exception_tags) do - vector:Add(v) - end -end - -local function parse_maxspeed(source) - if source == nil then - return 0 - end - local n = tonumber(source:match("%d*")) - if n == nil then - n = 0 - end - if string.match(source, "mph") or string.match(source, "mp/h") then - n = (n*1609)/1000; - end - return math.abs(n) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end end function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; + local barrier = node.tags:Find ("barrier") + local access = Access.find_access_tag(node, access_tags_hierachy) + local traffic_signal = node.tags:Find("highway") + + --flag node if it carries a traffic light + + if traffic_signal == "traffic_signals" then + node.traffic_light = true; + end + + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + return + else + node.bollard = true + end end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end - end - return 1 + return 1 end function way_function (way, numberOfNodesInWay) - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; + -- A way must have two nodes or more + if(numberOfNodesInWay < 2) then + return 0; + end + + -- First, get the properties of each way that we come across + local highway = way.tags:Find("highway") + local name = way.tags:Find("name") + local ref = way.tags:Find("ref") + local junction = way.tags:Find("junction") + local route = way.tags:Find("route") + local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) + local barrier = way.tags:Find("barrier") + local oneway = way.tags:Find("oneway") + local cycleway = way.tags:Find("cycleway") + local duration = way.tags:Find("duration") + local service = way.tags:Find("service") + local area = way.tags:Find("area") + local access = Access.find_access_tag(way, access_tags_hierachy) + + -- Second, parse the way according to these properties + + if ignore_areas and ("yes" == area) then + return 0 + end + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] then + return 0 end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = Access.find_access_tag(way, access_tags_hierachy) - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name -- else -- way.name = highway -- if no name exists, use way type - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - if (speed_profile[route] ~= nil and speed_profile[route] > 0) then - if durationIsValid(duration) then - way.duration = math.max( parseDuration(duration), 1 ); - end - way.direction = Way.bidirectional - if speed_profile[route] ~= nil then - highway = route; - end - if tonumber(way.duration) < 0 then - way.speed = speed_profile[highway] - end - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile[highway], maxspeed) - end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - if durationIsValid(duration) then - way.duration = math.max( parseDuration(duration), 1 ); - end - - - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end - - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end - - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel + end - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 - return 1 + if "roundabout" == junction then + way.roundabout = true; + end + + -- Handling ferries and piers + if (speed_profile[route] ~= nil and speed_profile[route] > 0) then + if durationIsValid(duration) then + way.duration = math.max( parseDuration(duration), 1 ); + end + way.direction = Way.bidirectional + if speed_profile[route] ~= nil then + highway = route; + end + if tonumber(way.duration) < 0 then + way.speed = speed_profile[highway] + end + end + + -- Set the avg speed on the way if it is accessible by road class + if (speed_profile[highway] ~= nil and way.speed == -1 ) then + if maxspeed > speed_profile[highway] then + way.speed = maxspeed + else + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile[highway], maxspeed) + end + end + + -- Set the avg speed on ways that are marked accessible + if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile["default"], maxspeed) + end + + if durationIsValid(duration) then + way.duration = math.max( parseDuration(duration), 1 ); + end + + -- Set access restriction flag if access is allowed under certain restrictions only + if access ~= "" and access_tag_restricted[access] then + way.is_access_restricted = true + end + + -- Set access restriction flag if service is allowed under certain restrictions only + if service ~= "" and service_tag_restricted[service] then + way.is_access_restricted = true + end + + -- Set direction according to tags on way + if obey_oneway then + if oneway == "no" or oneway == "0" or oneway == "false" then + way.direction = Way.bidirectional + elseif oneway == "-1" then + way.direction = Way.opposite + elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then + way.direction = Way.oneway + else + way.direction = Way.bidirectional + end + else + way.direction = Way.bidirectional + end + + -- Override general direction settings of there is a specific one for our mode of travel + if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then + way.ignore_in_grid = true + end + way.type = 1 +return 1 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 +for v in vector.nodes do + node_function(v) +end end From ee42d94e2d6f28b1d88a98e4a389c3f86cadc55d Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 4 Feb 2013 13:10:31 +0100 Subject: [PATCH 119/161] Fix test to reflect changed maxspeed behavior --- features/car/maxspeed.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 5b7c66ab0..639c1a1e4 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -19,7 +19,7 @@ Feature: Car - Max speed restrictions | a | b | ab | 42s ~10% | | b | c | bc | 360s ~10% | - Scenario: Car - Ignore maxspeed when higher than way speed + Scenario: Car - Do not ignore maxspeed when higher than way speed Given the node map | a | b | c | From 7c5ca8f1998843d80a56209135a8228f155e7f11 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 4 Feb 2013 13:11:03 +0100 Subject: [PATCH 120/161] ignore changes on profile symlink --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ccedb3d78..b8ca61d98 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,5 @@ stxxl.errlog ################### /sandbox/ -/test/profile.lua \ No newline at end of file +/test/profile.lua +/profile.lua From 54cdf6d6f215ad8b6556ed442adddd56cd7a9a30 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 4 Feb 2013 15:58:35 +0100 Subject: [PATCH 121/161] maxspeed:forward and :backward get parsed and tests pass. Implements #569 partially. --- features/bicycle/maxspeed.feature | 3 +-- features/car/maxspeed.feature | 3 +-- profiles/bicycle.lua | 15 +++++++++++++++ profiles/car.lua | 17 +++++++++++++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 892daeba4..9daf29ef2 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -32,13 +32,12 @@ Feature: Bike - Max speed restrictions | a | b | ab | 20s ~5% | | b | c | bc | 20s ~5% | - @todo Scenario: Bike - Forward/backward maxspeed Given the shortcuts | key | value | | bike | 43s ~10% | | run | 73s ~10% | - | walk | 170s ~10% | + | walk | 145s ~10% | | snail | 720s ~10% | Then routability should be diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index f0d038724..34cfec0ad 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -33,13 +33,12 @@ Feature: Car - Max speed restrictions | a | b | ab | 144s ~10% | | b | c | bc | 144s ~10% | - @todo Scenario: Car - Forward/backward maxspeed Given the shortcuts | key | value | | car | 12s ~10% | | run | 73s ~10% | - | walk | 170s ~10% | + | walk | 146s ~10% | | snail | 720s ~10% | And a grid size of 100 meters diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 8c518a6f0..81cb65236 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -143,6 +143,8 @@ function way_function (way, numberOfNodesInWay) local ref = way.tags:Find("ref") local junction = way.tags:Find("junction") local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") local onewayClass = way.tags:Find("oneway:bicycle") @@ -287,6 +289,19 @@ function way_function (way, numberOfNodesInWay) way.speed = math.min(way.speed, maxspeed) end end + + -- Override speed settings if explicit forward/backward maxspeeds are given + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + if Way.bidirectional == way.direction then + way.backward_speed = way.speed + end + way.speed = maxspeed_forward + end + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + way.backward_speed = maxspeed_backward + end + + way.type = 1 return 1 diff --git a/profiles/car.lua b/profiles/car.lua index c078647f6..676e21fb2 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -102,6 +102,8 @@ function way_function (way, numberOfNodesInWay) local junction = way.tags:Find("junction") local route = way.tags:Find("route") local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") local cycleway = way.tags:Find("cycleway") @@ -157,7 +159,7 @@ function way_function (way, numberOfNodesInWay) end way.speed = math.min(speed_profile[highway], maxspeed) end - + -- Set the avg speed on ways that are marked accessible if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then if 0 == maxspeed then @@ -190,7 +192,18 @@ function way_function (way, numberOfNodesInWay) else way.direction = Way.bidirectional end - + + -- Override speed settings if explicit forward/backward maxspeeds are given + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + if Way.bidirectional == way.direction then + way.backward_speed = way.speed + end + way.speed = maxspeed_forward + end + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + way.backward_speed = maxspeed_backward + end + -- Override general direction settings of there is a specific one for our mode of travel if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then From 9e11e832dacce7f917326dfddb9378ddbaf155d6 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 5 Feb 2013 09:50:14 +0100 Subject: [PATCH 122/161] fixing symlink --- profile.lua | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 120000 profile.lua diff --git a/profile.lua b/profile.lua deleted file mode 100644 index bad7e6bb5..000000000 --- a/profile.lua +++ /dev/null @@ -1 +0,0 @@ -profiles/car.lua \ No newline at end of file diff --git a/profile.lua b/profile.lua new file mode 120000 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file From c2be6bc019df8456d580bc00790fc9311b0a9465 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 5 Feb 2013 16:06:10 +0100 Subject: [PATCH 123/161] Fixes issue #567 --- Util/StringUtil.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Util/StringUtil.h b/Util/StringUtil.h index 0dc6df007..b09ac166a 100644 --- a/Util/StringUtil.h +++ b/Util/StringUtil.h @@ -131,7 +131,8 @@ inline void stringSplit(const std::string &s, const char delim, std::vector", "'", "[", "]", "\\"}; static std::string entities[] = {"&", """, "<", ">", "'", "&91;", "&93;", " \" }; -inline std::string HTMLEntitize( std::string & result) { +inline std::string HTMLEntitize( const std::string & input) { + std::string result(input); for(unsigned i = 0; i < sizeof(originals)/sizeof(std::string); ++i) { replaceAll(result, originals[i], entities[i]); } From 0b1d268b09b6ce85de978539e13e0dff31ed384b Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 6 Feb 2013 15:23:57 +0100 Subject: [PATCH 124/161] Fixing issue that enters infinite loop under certain conditions --- RoutingAlgorithms/AlternativePathRouting.h | 27 ++++++---- RoutingAlgorithms/ShortestPathRouting.h | 58 +++++++++++----------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h index bd542e1a3..4cd256b98 100644 --- a/RoutingAlgorithms/AlternativePathRouting.h +++ b/RoutingAlgorithms/AlternativePathRouting.h @@ -419,6 +419,13 @@ private: super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path); NodeID s_P = *s_v_middle, t_P = *v_t_middle; + if(UINT_MAX == s_P) { + return false; + } + + if(UINT_MAX == t_P) { + return false; + } const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath; int unpackedUntilDistance = 0; @@ -504,19 +511,21 @@ private: lengthOfPathT_Test_Path += unpackedUntilDistance; //Run actual T-Test query and compare if distances equal. - QueryHeap& forwardHeap = *super::_queryData.forwardHeap3; - QueryHeap& backwardHeap = *super::_queryData.backwardHeap3; + super::_queryData.InitializeOrClearThirdThreadLocalStorage(); + + QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3; + QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3; int _upperBound = INT_MAX; NodeID middle = UINT_MAX; - forwardHeap.Insert(s_P, 0, s_P); - backwardHeap.Insert(t_P, 0, t_P); + forward_heap3.Insert(s_P, 0, s_P); + backward_heap3.Insert(t_P, 0, t_P); //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while (forwardHeap.Size() + backwardHeap.Size() > 0) { - if (forwardHeap.Size() > 0) { - super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true); + while (forward_heap3.Size() + backward_heap3.Size() > 0) { + if (forward_heap3.Size() > 0) { + super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true); } - if (backwardHeap.Size() > 0) { - super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false); + if (backward_heap3.Size() > 0) { + super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false); } } return (_upperBound <= lengthOfPathT_Test_Path); diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index 4799d49d3..66d374079 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -53,53 +53,57 @@ public: super::_queryData.InitializeOrClearFirstThreadLocalStorage(); super::_queryData.InitializeOrClearSecondThreadLocalStorage(); + super::_queryData.InitializeOrClearThirdThreadLocalStorage(); - QueryHeap & forwardHeap = *super::_queryData.forwardHeap; - QueryHeap & backwardHeap = *super::_queryData.backwardHeap; - QueryHeap & forwardHeap2 = *super::_queryData.forwardHeap2; - QueryHeap & backwardHeap2 = *super::_queryData.backwardHeap2; + QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap); + QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap); + QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2); + QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2); //Get distance to next pair of target nodes. BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) { - forwardHeap.Clear(); forwardHeap2.Clear(); - backwardHeap.Clear(); backwardHeap2.Clear(); + forward_heap1.Clear(); forward_heap2.Clear(); + reverse_heap1.Clear(); reverse_heap2.Clear(); int _localUpperbound1 = INT_MAX; int _localUpperbound2 = INT_MAX; + middle1 = UINT_MAX; + middle2 = UINT_MAX; + //insert new starting nodes into forward heap, adjusted by previous distances. if(searchFrom1stStartNode) { - forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); - forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); + forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); } if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) { - forwardHeap.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); - forwardHeap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); + forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1); } //insert new backward nodes into backward heap, unadjusted. - backwardHeap.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); + reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode); if(phantomNodePair.targetPhantom.isBidirected() ) { - backwardHeap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); + reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1); } const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0); const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0); //run two-Target Dijkstra routing step. - while(0 < (forwardHeap.Size() + backwardHeap.Size() )){ - if(0 < forwardHeap.Size()){ - super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, forward_offset, true); + while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){ + if(0 < forward_heap1.Size()){ + super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true); } - if(0 < backwardHeap.Size() ){ - super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, reverse_offset, false); + if(0 < reverse_heap1.Size() ){ + super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false); } } - if(0 < backwardHeap2.Size()) { - while(0 < (forwardHeap2.Size() + backwardHeap2.Size() )){ - if(0 < forwardHeap2.Size()){ - super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, forward_offset, true); + if(0 < reverse_heap2.Size()) { + while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){ + if(0 < forward_heap2.Size()){ + super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true); } - if(0 < backwardHeap2.Size()){ - super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, reverse_offset, false); + if(0 < reverse_heap2.Size()){ + super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false); } } } @@ -111,13 +115,9 @@ public: } if(UINT_MAX == middle1) { searchFrom1stStartNode = false; - } else { - searchFrom1stStartNode = true; } if(UINT_MAX == middle2) { searchFrom2ndStartNode = false; - } else { - searchFrom2ndStartNode = true; } //Was at most one of the two paths not found? @@ -127,11 +127,11 @@ public: std::vector temporaryPackedPath1; std::vector temporaryPackedPath2; if(INT_MAX != _localUpperbound1) { - super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1); + super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1); } if(INT_MAX != _localUpperbound2) { - super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2); + super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2); } //if one of the paths was not found, replace it with the other one. From a4e322f085e0dbebd158d4baaa871d48051fdfdc Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Wed, 6 Feb 2013 16:58:18 +0100 Subject: [PATCH 125/161] don't allow bikes on highway=construction, fixes #582 --- features/bicycle/pushing.feature | 9 +++++++++ features/bicycle/train.feature | 7 +++++++ profiles/bicycle.lua | 7 ++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 37dff3d1f..8e2ca3052 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -70,3 +70,12 @@ Feature: Bike - Accessability of different way types | motorway | | | | | | motorway | yes | | foot | | | motorway | | yes | | foot | + + @construction + Scenario: Bike - Don't allow routing on ways still under construction + Then routability should be + | highway | foot | bicycle | bothw | + | primary | | | x | + | construction | | | | + | construction | yes | | | + | construction | | yes | | diff --git a/features/bicycle/train.feature b/features/bicycle/train.feature index 1b5699f16..a4af362b5 100644 --- a/features/bicycle/train.feature +++ b/features/bicycle/train.feature @@ -30,3 +30,10 @@ Bringing bikes on trains and subways | (nil) | some_tag | | | | (nil) | some_tag | no | | | (nil) | some_tag | yes | x | + + @construction + Scenario: Bike - Don't route on railways under construction + Then routability should be + | highway | railway | bicycle | bothw | + | primary | | | x | + | (nil) | construction | yes | | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 7d51e8091..c5c2f64fb 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -130,7 +130,12 @@ function way_function (way, numberOfNodesInWay) then return 0 end - + + -- don't route on ways or railways that are still under construction + if highway=='construction' or railway=='construction' then + return 0 + end + -- access local access = Access.find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then From 1a442c36e9b5381a30e7b6b90bbe2acbd6253009 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Sun, 10 Feb 2013 15:05:31 +0100 Subject: [PATCH 126/161] Implementing #566 --- profiles/car.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/car.lua b/profiles/car.lua index 6dfaf5ce1..095806590 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -1,7 +1,7 @@ -- Begin of globals require("lib/access") -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true} +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = 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 } access_tag_restricted = { ["destination"] = true, ["delivery"] = true } From 3d1a85bbea9d63de5b673422a98804127994a7cd Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sun, 10 Feb 2013 18:18:39 +0100 Subject: [PATCH 127/161] Fixing compilation issues on various compilers, i.e. old GCC, clang, ICPC --- Extractor/ExtractorStructs.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index 644408ca4..fe21da957 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -61,9 +61,10 @@ struct ExtractionWay { ignoreInGrid = false; } - enum { + enum Directions { notSure = 0, oneway, bidirectional, opposite - } direction; + }; + Directions direction; unsigned id; unsigned nameID; std::string name; From 918c9785517e1ff8fd634ab2088773e7b36103a4 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 11 Feb 2013 15:06:33 +0100 Subject: [PATCH 128/161] Fixes issue #585 --- Contractor/EdgeBasedGraphFactory.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index d7ea8e6e0..6d52f333b 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -302,7 +302,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { } p.printIncrement(); } - numberOfOriginalEdges += originalEdgeData.size(); originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData)); originalEdgeDataOutFile.seekp(std::ios::beg); originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned)); From 1c0202e7904884f6823b0bf3a9192a1e1c7fde6e Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 11 Feb 2013 15:20:37 +0100 Subject: [PATCH 129/161] Reordering initializations --- Contractor/EdgeBasedGraphFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 6d52f333b..968adf731 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -21,8 +21,8 @@ #include "EdgeBasedGraphFactory.h" template<> -EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector & inputEdges, std::vector & bn, std::vector & tl, std::vector<_Restriction> & irs, std::vector & nI, SpeedProfileProperties sp) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()), speedProfile(sp) { - BOOST_FOREACH(_Restriction & restriction, irs) { +EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector & inputEdges, std::vector & bn, std::vector & tl, std::vector<_Restriction> & irs, std::vector & nI, SpeedProfileProperties sp) : speedProfile(sp), inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) { + BOOST_FOREACH(const _Restriction & restriction, irs) { std::pair restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode); unsigned index; RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource); From 6410314b0b4fdde8aad276380c1ee5af4cbf26fc Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 12 Feb 2013 10:57:33 +0100 Subject: [PATCH 130/161] Add license attribution to GPX output --- Descriptors/GPXDescriptor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 17a3f9226..5096468fb 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -39,6 +39,7 @@ public: "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd" "\">"; + reply.content += "Data (c) OpenStreetMap contributors (ODbL)"; reply.content += ""; if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) { convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp); From 4d017f5d495ea32e7c021803c66eeca40208fdf7 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 12 Feb 2013 11:35:59 +0100 Subject: [PATCH 131/161] Saving 4 bytes per edge --- Algorithms/StronglyConnectedComponents.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Algorithms/StronglyConnectedComponents.h b/Algorithms/StronglyConnectedComponents.h index 148e35613..a83110034 100644 --- a/Algorithms/StronglyConnectedComponents.h +++ b/Algorithms/StronglyConnectedComponents.h @@ -52,21 +52,12 @@ private: unsigned edgeBasedNodeID; unsigned nameID:31; bool shortcut:1; + short type; + bool isAccessRestricted:1; bool forward:1; bool backward:1; bool roundabout:1; bool ignoreInGrid:1; - short type; - bool isAccessRestricted; - }; - - struct _EdgeBasedEdgeData { - int distance; - unsigned via; - unsigned nameID; - bool forward; - bool backward; - TurnInstruction turnInstruction; }; typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; From 906d28fa5de5c0d0ddabe109033a0f60a9deb947 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 12 Feb 2013 15:23:09 +0100 Subject: [PATCH 132/161] Correct wrong allocation, use std::vector for node array and pass PODs by value not ref --- DataStructures/DynamicGraph.h | 44 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h index 64bfa6087..6730babdf 100644 --- a/DataStructures/DynamicGraph.h +++ b/DataStructures/DynamicGraph.h @@ -59,8 +59,8 @@ class DynamicGraph { { m_numNodes = nodes; m_numEdges = ( EdgeIterator ) graph.size(); - m_nodes.reserve( m_numNodes ); - m_nodes.resize( m_numNodes ); + m_nodes.reserve( m_numNodes +1); + m_nodes.resize( m_numNodes +1); EdgeIterator edge = 0; EdgeIterator position = 0; for ( NodeIterator node = 0; node < m_numNodes; ++node ) { @@ -98,40 +98,33 @@ class DynamicGraph { return m_numEdges; } - unsigned GetOutDegree( const NodeIterator &n ) const - { + unsigned GetOutDegree( const NodeIterator n ) const { return m_nodes[n].edges; } - NodeIterator GetTarget( const EdgeIterator &e ) const - { + NodeIterator GetTarget( const EdgeIterator e ) const { return NodeIterator( m_edges[e].target ); } - EdgeDataT &GetEdgeData( const EdgeIterator &e ) - { + EdgeDataT &GetEdgeData( const EdgeIterator e ) { return m_edges[e].data; } - const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const - { + const EdgeDataT &GetEdgeData( const EdgeIterator e ) const { return m_edges[e].data; } - EdgeIterator BeginEdges( const NodeIterator &n ) const - { + EdgeIterator BeginEdges( const NodeIterator n ) const { //assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 ); return EdgeIterator( m_nodes[n].firstEdge ); } - EdgeIterator EndEdges( const NodeIterator &n ) const - { + EdgeIterator EndEdges( const NodeIterator n ) const { return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges ); } //adds an edge. Invalidates edge iterators for the source node - EdgeIterator InsertEdge( const NodeIterator &from, const NodeIterator &to, const EdgeDataT &data ) - { + EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) { Node &node = m_nodes[from]; EdgeIterator newFirstEdge = node.edges + node.firstEdge; if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) { @@ -165,7 +158,7 @@ class DynamicGraph { } //removes an edge. Invalidates edge iterators for the source node - void DeleteEdge( const NodeIterator source, const EdgeIterator &e ) { + void DeleteEdge( const NodeIterator source, const EdgeIterator e ) { Node &node = m_nodes[source]; --m_numEdges; --node.edges; @@ -176,8 +169,7 @@ class DynamicGraph { } //removes all edges (source,target) - int DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) - { + int DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) { int deleted = 0; for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) { if ( m_edges[i].target == target ) { @@ -197,8 +189,7 @@ class DynamicGraph { } //searches for a specific edge - EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const - { + EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const { for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) { if ( m_edges[i].target == to ) { return i; @@ -209,13 +200,11 @@ class DynamicGraph { protected: - bool isDummy( EdgeIterator edge ) const - { + bool isDummy( EdgeIterator edge ) const { return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)(); } - void makeDummy( EdgeIterator edge ) - { + void makeDummy( EdgeIterator edge ) { m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)(); } @@ -234,9 +223,8 @@ class DynamicGraph { NodeIterator m_numNodes; EdgeIterator m_numEdges; - DeallocatingVector< Node > m_nodes; - DeallocatingVector< Edge > m_edges; - + std::vector< Node > m_nodes; + DeallocatingVector< Edge > m_edges; }; #endif // DYNAMICGRAPH_H_INCLUDED From 7e39c43896e13bbd5d5f115b8fcda0bdbaccd162 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 12 Feb 2013 15:24:35 +0100 Subject: [PATCH 133/161] allocate data in chunks of 8MB --- DataStructures/DeallocatingVector.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DataStructures/DeallocatingVector.h b/DataStructures/DeallocatingVector.h index d3c19d170..c3f922c85 100644 --- a/DataStructures/DeallocatingVector.h +++ b/DataStructures/DeallocatingVector.h @@ -32,7 +32,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #endif -template +template class DeallocatingVectorIterator : public std::iterator { protected: @@ -185,7 +185,7 @@ public: } }; -template +template class DeallocatingVector { private: size_t mCurrentSize; From 0f03beb2b5dce6a98d528ab90e6291a4c78d057d Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 12 Feb 2013 15:46:40 +0100 Subject: [PATCH 134/161] replacing c-style size_t with the one from std namespace --- DataStructures/DeallocatingVector.h | 61 ++++++++++++++--------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/DataStructures/DeallocatingVector.h b/DataStructures/DeallocatingVector.h index c3f922c85..89d8e2ce7 100644 --- a/DataStructures/DeallocatingVector.h +++ b/DataStructures/DeallocatingVector.h @@ -22,7 +22,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #define DEALLOCATINGVECTOR_H_ #include -#include #include #if __cplusplus > 199711L @@ -32,7 +31,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #endif -template +template class DeallocatingVectorIterator : public std::iterator { protected: @@ -42,12 +41,12 @@ protected: DeallocatingVectorIteratorState(); public: explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {} - //explicit DeallocatingVectorIteratorState(const ElementT * ptr, const size_t idx, const std::vector & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {} - explicit DeallocatingVectorIteratorState(const size_t idx, std::vector & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) { + //explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {} + explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) { setPointerForIndex(); } ElementT * mData; - size_t mIndex; + std::size_t mIndex; std::vector & mBucketList; inline void setPointerForIndex() { @@ -55,8 +54,8 @@ protected: mData = DEALLOCATION_VECTOR_NULL_PTR; return; } - size_t _bucket = mIndex/bucketSizeC; - size_t _index = mIndex%bucketSizeC; + std::size_t _bucket = mIndex/bucketSizeC; + std::size_t _index = mIndex%bucketSizeC; mData = &(mBucketList[_bucket][_index]); if(DeallocateC) { @@ -104,8 +103,8 @@ public: template DeallocatingVectorIterator(const DeallocatingVectorIterator & r) : mState(r.mState) {} - DeallocatingVectorIterator(size_t idx, std::vector & input_list) : mState(idx, input_list) {} - //DeallocatingVectorIterator(size_t idx, const std::vector & input_list) : mState(idx, input_list) {} + DeallocatingVectorIterator(std::size_t idx, std::vector & input_list) : mState(idx, input_list) {} + //DeallocatingVectorIterator(std::size_t idx, const std::vector & input_list) : mState(idx, input_list) {} DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {} template @@ -185,10 +184,10 @@ public: } }; -template +template class DeallocatingVector { private: - size_t mCurrentSize; + std::size_t mCurrentSize; std::vector mBucketList; public: @@ -227,21 +226,21 @@ public: } inline void push_back(const ElementT & element) { - size_t _capacity = capacity(); + std::size_t _capacity = capacity(); if(mCurrentSize == _capacity) { mBucketList.push_back(new ElementT[bucketSizeC]); } - size_t _index = size()%bucketSizeC; + std::size_t _index = size()%bucketSizeC; mBucketList.back()[_index] = element; ++mCurrentSize; } - inline void reserve(const size_t) const { + inline void reserve(const std::size_t) const { //don't do anything } - inline void resize(const size_t new_size) { + inline void resize(const std::size_t new_size) { if(new_size > mCurrentSize) { while(capacity() < new_size) { mBucketList.push_back(new ElementT[bucketSizeC]); @@ -249,7 +248,7 @@ public: mCurrentSize = new_size; } if(new_size < mCurrentSize) { - size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC); + std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC); for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) { delete[] mBucketList[i]; @@ -259,16 +258,16 @@ public: } } - inline size_t size() const { + inline std::size_t size() const { return mCurrentSize; } - inline size_t capacity() const { + inline std::size_t capacity() const { return mBucketList.size() * bucketSizeC; } inline iterator begin() { - return iterator(static_cast(0), mBucketList); + return iterator(static_cast(0), mBucketList); } inline iterator end() { @@ -276,7 +275,7 @@ public: } inline deallocation_iterator dbegin() { - return deallocation_iterator(static_cast(0), mBucketList); + return deallocation_iterator(static_cast(0), mBucketList); } inline deallocation_iterator dend() { @@ -284,34 +283,34 @@ public: } inline const_iterator begin() const { - return const_iterator(static_cast(0), mBucketList); + return const_iterator(static_cast(0), mBucketList); } inline const_iterator end() const { return const_iterator(size(), mBucketList); } - inline ElementT & operator[](const size_t index) { - size_t _bucket = index / bucketSizeC; - size_t _index = index % bucketSizeC; + inline ElementT & operator[](const std::size_t index) { + std::size_t _bucket = index / bucketSizeC; + std::size_t _index = index % bucketSizeC; return (mBucketList[_bucket][_index]); } - const inline ElementT & operator[](const size_t index) const { - size_t _bucket = index / bucketSizeC; - size_t _index = index % bucketSizeC; + const inline ElementT & operator[](const std::size_t index) const { + std::size_t _bucket = index / bucketSizeC; + std::size_t _index = index % bucketSizeC; return (mBucketList[_bucket][_index]); } inline ElementT & back() { - size_t _bucket = mCurrentSize / bucketSizeC; - size_t _index = mCurrentSize % bucketSizeC; + std::size_t _bucket = mCurrentSize / bucketSizeC; + std::size_t _index = mCurrentSize % bucketSizeC; return (mBucketList[_bucket][_index]); } const inline ElementT & back() const { - size_t _bucket = mCurrentSize / bucketSizeC; - size_t _index = mCurrentSize % bucketSizeC; + std::size_t _bucket = mCurrentSize / bucketSizeC; + std::size_t _index = mCurrentSize % bucketSizeC; return (mBucketList[_bucket][_index]); } }; From f780aa6160df671ed78c859247eeca951df7f7ba Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Thu, 14 Feb 2013 17:11:18 +0100 Subject: [PATCH 135/161] Saving 4 bytes on each original edge. Simplifying handling of original edge data --- Contractor/EdgeBasedGraphFactory.cpp | 25 ++++++++++++++----------- Contractor/EdgeBasedGraphFactory.h | 5 ++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 968adf731..13a570e46 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -234,6 +234,9 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { std::vector().swap(vectorOfComponentSizes); std::vector().swap(componentsIndex); + std::vector original_edge_data_vector; + original_edge_data_vector.reserve(10000); + //Loop over all turns and generate new set of edges. //Three nested loop look super-linear, but we are dealing with a linear number of turns only. for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) { @@ -271,8 +274,9 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { distance += speedProfile.trafficSignalPenalty; } TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); - if(turnInstruction == TurnInstructions.UTurn) + if(TurnInstructions.UTurn == turnInstruction) { distance += speedProfile.uTurnPenalty; + } // if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) { // distance += TurnInstructions.AccessRestrictionPenalty; // turnInstruction |= TurnInstructions.AccessRestrictionFlag; @@ -282,17 +286,16 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { //distance += heightPenalty; //distance += ComputeTurnPenalty(u, v, w); assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID); - if(originalEdgeData.size() == originalEdgeData.capacity()-3) { - originalEdgeData.reserve(originalEdgeData.size()*1.2); - } OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction); - EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false ); - originalEdgeData.push_back(oed); - if(originalEdgeData.size() > 100000) { - originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData)); - originalEdgeData.clear(); - } + original_edge_data_vector.push_back(oed); ++numberOfOriginalEdges; + + if(original_edge_data_vector.size() > 100000) { + originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData)); + original_edge_data_vector.clear(); + } + + EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false ); edgeBasedEdges.push_back(newEdge); } else { ++numberOfSkippedTurns; @@ -302,7 +305,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { } p.printIncrement(); } - originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData)); + originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData)); originalEdgeDataOutFile.seekp(std::ios::beg); originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned)); originalEdgeDataOutFile.close(); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 45ac0ad39..1198ae971 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -82,13 +82,13 @@ private: unsigned edgeBasedNodeID; unsigned nameID; short type; - bool isAccessRestricted; + bool isAccessRestricted:1; bool shortcut:1; bool forward:1; bool backward:1; bool roundabout:1; bool ignoreInGrid:1; - bool contraFlow; + bool contraFlow:1; }; struct _EdgeBasedEdgeData { @@ -118,7 +118,6 @@ private: DeallocatingVector edgeBasedEdges; DeallocatingVector edgeBasedNodes; - std::vector originalEdgeData; NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const; bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const; From f315a013b8fc356b570ee1860c089d0539927afe Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Thu, 14 Feb 2013 17:12:12 +0100 Subject: [PATCH 136/161] Refactoring InputEdge type and removing dead code --- DataStructures/ImportEdge.h | 71 +++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index 1b5966c40..714560ccc 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. -*/ + */ #ifndef EDGE_H #define EDGE_H @@ -41,7 +41,7 @@ public: } explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) : - _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; } + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -95,43 +95,46 @@ public: template EdgeBasedEdge(const EdgeT & myEdge ) : - _source(myEdge.source), - _target(myEdge.target), - _edgeID(myEdge.data.via), -// _nameID1(myEdge.data.nameID), - _weight(myEdge.data.distance), - _forward(myEdge.data.forward), - _backward(myEdge.data.backward)//, -// _turnInstruction(myEdge.data.turnInstruction) - { } + m_source(myEdge.source), + m_target(myEdge.target), + m_edgeID(myEdge.data.via), + m_weight(myEdge.data.distance), + m_forward(myEdge.data.forward), + m_backward(myEdge.data.backward) + { } /** Default constructor. target and weight are set to 0.*/ EdgeBasedEdge() : - _source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { } + m_source(0), + m_target(0), + m_edgeID(0), + m_weight(0), + m_forward(false), + m_backward(false) + { } - explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, EdgeWeight w, bool f, bool b) : - _source(s), _target(t), _edgeID(v), _weight(w), _forward(f), _backward(b){} + explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) : + m_source(s), + m_target(t), + m_edgeID(v), + m_weight(w), + m_forward(f), + m_backward(b) + {} - NodeID target() const {return _target; } - NodeID source() const {return _source; } - EdgeWeight weight() const {return _weight; } - NodeID id() const { return _edgeID; } - bool isBackward() const { return _backward; } - bool isForward() const { return _forward; } - - NodeID _source; - NodeID _target; - NodeID _edgeID; - EdgeWeight _weight:30; - bool _forward:1; - bool _backward:1; -}; - -struct MinimalEdgeData { -public: - EdgeWeight distance; - bool forward; - bool backward; + NodeID target() const {return m_target; } + NodeID source() const {return m_source; } + EdgeWeight weight() const {return m_weight; } + NodeID id() const { return m_edgeID; } + bool isBackward() const { return m_backward; } + bool isForward() const { return m_forward; } +private: + NodeID m_source; + NodeID m_target; + NodeID m_edgeID; + EdgeWeight m_weight:30; + bool m_forward:1; + bool m_backward:1; }; typedef NodeBasedEdge ImportEdge; From cad0069be27fcac8ae46be0802e1d53e3c74c8ab Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Thu, 14 Feb 2013 17:12:52 +0100 Subject: [PATCH 137/161] Minor refactoring/reordering --- createHierarchy.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 9bc150ed8..806164132 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -58,6 +58,7 @@ std::vector internalToExternalNodeMapping; std::vector<_Restriction> inputRestrictions; std::vector bollardNodes; std::vector trafficLightNodes; +std::vector edgeList; int main (int argc, char *argv[]) { if(argc < 3) { @@ -133,8 +134,6 @@ int main (int argc, char *argv[]) { } speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); - - std::vector edgeList; NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); in.close(); INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights"); @@ -156,6 +155,9 @@ int main (int argc, char *argv[]) { NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes(); DeallocatingVector edgeBasedEdgeList; edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList); + DeallocatingVector nodeBasedEdgeList; + edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); + delete edgeBasedGraphFactory; /*** * Writing info on original (node-based) nodes @@ -167,12 +169,6 @@ int main (int argc, char *argv[]) { mapOutFile.close(); std::vector().swap(internalToExternalNodeMapping); - /*** - * Writing info on original (node-based) edges - */ - DeallocatingVector nodeBasedEdgeList; - edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); - delete edgeBasedGraphFactory; double expansionHasFinishedTime = get_timestamp() - startupTime; /*** @@ -213,7 +209,7 @@ int main (int argc, char *argv[]) { INFO("Serializing compacted graph"); std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary); - BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) { + BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { if(edge.source > numberOfNodes) { numberOfNodes = edge.source; } From 9a44f16846f177b691d5341762383d6fd126ffc9 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 15 Feb 2013 17:02:49 +0100 Subject: [PATCH 138/161] don't push against oneway flow on roundabout. fixes #591 --- features/bicycle/pushing.feature | 6 ++++++ profiles/bicycle.lua | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 8e2ca3052..1c6919706 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -79,3 +79,9 @@ Feature: Bike - Accessability of different way types | construction | | | | | construction | yes | | | | construction | | yes | | + + @roundabout + Scenario: Bike - Don't push bikes against oneway flow on roundabouts + Then routability should be + | junction | forw | backw | + | roundabout | x | | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index c5c2f64fb..92f9ba812 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -263,12 +263,14 @@ function way_function (way, numberOfNodesInWay) -- pushing bikes if bicycle_speeds[highway] or pedestrian_speeds[highway] then if foot ~= 'no' then - if way.direction == Way.oneway then - way.backward_speed = walking_speed - elseif way.direction == Way.opposite then - way.backward_speed = walking_speed - way.speed = way.speed - end + if junction ~= "roundabout" then + if way.direction == Way.oneway then + way.backward_speed = walking_speed + elseif way.direction == Way.opposite then + way.backward_speed = walking_speed + way.speed = way.speed + end + end end if way.backward_speed == way.speed then -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal From 23254b4f24f33012403ee5e56e8e2d423c9e54ba Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 11 Feb 2013 11:02:21 +0100 Subject: [PATCH 139/161] update bike speeds --- profiles/bicycle.lua | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 92f9ba812..62a487e62 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -10,25 +10,25 @@ cycleway_tags = {["track"]=true,["lane"]=true,["opposite"]=true,["opposite_lane" service_tag_restricted = { ["parking_aisle"] = true } restriction_exception_tags = { "bicycle", "vehicle", "access" } -default_speed = 16 +default_speed = 15 -walking_speed = 4 +walking_speed = 6 bicycle_speeds = { - ["cycleway"] = 18, - ["primary"] = 17, - ["primary_link"] = 17, - ["secondary"] = 18, - ["secondary_link"] = 18, - ["tertiary"] = 18, - ["tertiary_link"] = 18, - ["residential"] = 18, - ["unclassified"] = 16, - ["living_street"] = 16, - ["road"] = 16, - ["service"] = 16, - ["track"] = 13, - ["path"] = 13 + ["cycleway"] = default_speed, + ["primary"] = default_speed, + ["primary_link"] = default_speed, + ["secondary"] = default_speed, + ["secondary_link"] = default_speed, + ["tertiary"] = default_speed, + ["tertiary_link"] = default_speed, + ["residential"] = default_speed, + ["unclassified"] = default_speed, + ["living_street"] = default_speed, + ["road"] = default_speed, + ["service"] = default_speed, + ["track"] = 12, + ["path"] = 12 --["footway"] = 12, --["pedestrian"] = 12, } @@ -69,7 +69,7 @@ obey_oneway = true obey_bollards = false use_restrictions = true ignore_areas = true -- future feature -traffic_signal_penalty = 2 +traffic_signal_penalty = 5 u_turn_penalty = 20 -- End of globals From 26e2f9ddd1c81804df9d6e8e67d14a8758bc7134 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 11 Feb 2013 11:03:24 +0100 Subject: [PATCH 140/161] add 'no' to barrier whitelist in bike profile --- profiles/bicycle.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 62a487e62..3a1544cf6 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,7 +1,7 @@ require("lib/access") -- 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} +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_restricted = { ["destination"] = true, ["delivery"] = true } From 94fa0047dbb8213d5a958727e42b8cd298923650 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 19 Feb 2013 08:54:23 +0100 Subject: [PATCH 141/161] update bike tests --- features/bicycle/maxspeed.feature | 24 ++++++++++++------------ features/bicycle/pushing.feature | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index b02fe4e33..9924f5596 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -7,35 +7,35 @@ Feature: Bike - Max speed restrictions Scenario: Bicycle - Respect maxspeeds when lower that way type speed Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | + | residential | | 49s ~10% | | residential | 10 | 72s ~10% | Scenario: Bicycle - Ignore maxspeed when higher than way speed Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | - | residential | 80 | 40s ~10% | + | residential | | 49s ~10% | + | residential | 80 | 49s ~10% | @todo Scenario: Bicycle - Maxspeed formats Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | + | residential | | 49s ~10% | | residential | 5 | 144s ~10% | | residential | 5mph | 90s ~10% | | residential | 5 mph | 90s ~10% | | residential | 5MPH | 90s ~10% | | residential | 5 MPH | 90s ~10% | - | trunk | 5unknown | 40s ~10% | - | trunk | 5 unknown | 40s ~10% | + | trunk | 5unknown | 49s ~10% | + | trunk | 5 unknown | 49s ~10% | @todo Scenario: Bicycle - Maxspeed special tags Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | - | residential | none | 40s ~10% | - | residential | signals | 40s ~10% | + | residential | | 49s ~10% | + | residential | none | 49s ~10% | + | residential | signals | 49s ~10% | Scenario: Bike - Do not use maxspeed when higher that way type speed Given the node map @@ -48,13 +48,13 @@ Feature: Bike - Max speed restrictions When I route I should get | from | to | route | time | - | a | b | ab | 20s ~5% | - | b | c | bc | 20s ~5% | + | a | b | ab | 24s ~5% | + | b | c | bc | 24s ~5% | Scenario: Bike - Forward/backward maxspeed Given the shortcuts | key | value | - | bike | 43s ~10% | + | bike | 49s ~10% | | run | 73s ~10% | | walk | 145s ~10% | | snail | 720s ~10% | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 1c6919706..169d340e3 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -5,8 +5,8 @@ Feature: Bike - Accessability of different way types Given the profile "bicycle" Given the shortcuts | key | value | - | bike | 40s ~20% | - | foot | 180s ~20% | + | bike | 49s ~20% | + | foot | 121s ~20% | Scenario: Bike - Pushing bikes on pedestrian-only ways Then routability should be From d59e526e1eca309fbed3fbf8a9370aa374fe9b7c Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 5 Feb 2013 17:26:35 +0100 Subject: [PATCH 142/161] lua setting for using turn restrictions --- Extractor/PBFParser.cpp | 13 +++++++++++-- Extractor/PBFParser.h | 3 ++- profiles/bicycle.lua | 2 ++ profiles/car.lua | 1 + 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 222475db6..299275b12 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -20,7 +20,7 @@ #include "PBFParser.h" -PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){ +PBFParser::PBFParser(const char * fileName) : externalMemory(NULL), use_turn_restrictions(true) { GOOGLE_PROTOBUF_VERIFY_VERSION; //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. @@ -43,7 +43,13 @@ void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) { void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { scriptingEnvironment = _se; - + + if(0 != luaL_dostring( scriptingEnvironment.getLuaStateForThreadID(0), "return use_turn_restrictions\n")) { + ERR(lua_tostring(scriptingEnvironment.getLuaStateForThreadID(0),-1)<< " occured in scripting block"); + } + use_turn_restrictions = lua_toboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1); + INFO("Use turn restrictions:" << use_turn_restrictions); + if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) { //get list of turn restriction exceptions try { @@ -241,6 +247,9 @@ inline void PBFParser::parseNode(_ThreadData * ) { inline void PBFParser::parseRelation(_ThreadData * threadData) { //TODO: leave early, if relation is not a restriction //TODO: reuse rawRestriction container + if( use_turn_restrictions==false ) + return; + const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); for(int i = 0; i < group.relations_size(); ++i ) { std::string exception_of_restriction_tag; diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index d3da02706..e00d64fbc 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -106,7 +106,8 @@ private: /* ThreadData Queue */ boost::shared_ptr > threadDataQueue; ScriptingEnvironment scriptingEnvironment; - + + bool use_turn_restrictions; std::vector restriction_exceptions_vector; }; diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index c5c2f64fb..2f476e307 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -64,6 +64,7 @@ man_made_speeds = { route_speeds = { ["ferry"] = 5 } + take_minimum_of_speeds = true obey_oneway = true obey_bollards = false @@ -71,6 +72,7 @@ use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 +use_turn_restrictions = true -- End of globals diff --git a/profiles/car.lua b/profiles/car.lua index 095806590..d2fa5cea3 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -39,6 +39,7 @@ use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 +use_turn_restrictions = true -- End of globals From 22c5c539c2fdc6bca9158dd7d300009354aca067 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 7 Feb 2013 16:16:39 +0100 Subject: [PATCH 143/161] default to using turn restrictions --- Extractor/PBFParser.cpp | 6 ++++-- profiles/bicycle.lua | 1 - profiles/car.lua | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 299275b12..3280e7e81 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -47,8 +47,10 @@ void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { if(0 != luaL_dostring( scriptingEnvironment.getLuaStateForThreadID(0), "return use_turn_restrictions\n")) { ERR(lua_tostring(scriptingEnvironment.getLuaStateForThreadID(0),-1)<< " occured in scripting block"); } - use_turn_restrictions = lua_toboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1); - INFO("Use turn restrictions:" << use_turn_restrictions); + if( lua_isboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1) ) { + use_turn_restrictions = lua_toboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1); + } + INFO("Use turn restrictions: " << (use_turn_restrictions ? "yes" : "no")); if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) { //get list of turn restriction exceptions diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 2f476e307..cb07ea6fb 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -72,7 +72,6 @@ use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 -use_turn_restrictions = true -- End of globals diff --git a/profiles/car.lua b/profiles/car.lua index d2fa5cea3..095806590 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -39,7 +39,6 @@ use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 -use_turn_restrictions = true -- End of globals From 1ecad20a0d09988ee40e53919ac2b5cedf5a956a Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 10 Feb 2013 10:59:54 +0100 Subject: [PATCH 144/161] support xml, move duplicated xml/pbf code to base --- Extractor/BaseParser.cpp | 113 +++++++++++++++++++++++++++++++++++++++ Extractor/BaseParser.h | 27 ++++++---- Extractor/PBFParser.cpp | 101 ++++------------------------------ Extractor/PBFParser.h | 23 ++------ Extractor/XMLParser.cpp | 101 +++++----------------------------- Extractor/XMLParser.h | 18 ++----- extractor.cpp | 15 +++--- features/support/data.rb | 5 +- 8 files changed, 173 insertions(+), 230 deletions(-) create mode 100644 Extractor/BaseParser.cpp diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp new file mode 100644 index 000000000..d84ebe034 --- /dev/null +++ b/Extractor/BaseParser.cpp @@ -0,0 +1,113 @@ +/* +open source routing machine +Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +#include "BaseParser.h" + +BaseParser::BaseParser(ExtractorCallbacks* em, ScriptingEnvironment& se) : +externalMemory(em), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { + luaState = se.getLuaStateForThreadID(0); + ReadUseRestrictionsSetting(); + ReadRestrictionExceptions(); +} + +void BaseParser::ReadUseRestrictionsSetting() { + if(0 != luaL_dostring( luaState, "return use_turn_restrictions\n")) { + ERR(lua_tostring( luaState,-1)<< " occured in scripting block"); + } + if( lua_isboolean( luaState, -1) ) { + use_turn_restrictions = lua_toboolean(luaState, -1); + } + if( use_turn_restrictions ) { + INFO("Using turn restrictions" ); + } else { + INFO("Ignoring turn restrictions" ); + } +} + +void BaseParser::ReadRestrictionExceptions() { + if(lua_function_exists(luaState, "get_exceptions" )) { + //get list of turn restriction exceptions + try { + luabind::call_function( + luaState, + "get_exceptions", + boost::ref(restriction_exceptions) + ); + INFO("Found " << restriction_exceptions.size() << " exceptions to turn restriction"); + BOOST_FOREACH(std::string & str, restriction_exceptions) { + INFO(" " << str); + } + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + } else { + INFO("Found no exceptions to turn restrictions"); + } +} + +void BaseParser::report_errors(lua_State *L, int status) { + if ( status!=0 ) { + std::cerr << "-- " << lua_tostring(L, -1) << std::endl; + lua_pop(L, 1); // remove error message + } +} + +inline void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { + try { + luabind::call_function( localLuaState, "node_function", boost::ref(n) ); + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } +} + +inline void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) { + try { + luabind::call_function( localLuaState, "way_function", boost::ref(w), w.path.size() ); + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } +} + +inline bool BaseParser::ShouldIgnoreRestriction(std::string& exception_string) { + //should this restriction be ignored? yes if there's an overlap between: + //a) the list of modes in the except tag of the restriction (exception_string), ex: except=bus;bicycle + //b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle] + + if( "" == exception_string ) + return false; + + //Be warned, this is quadratic work here, but we assume that + //only a few exceptions are actually defined. + std::vector exceptions; + boost::algorithm::split_regex(exceptions, exception_string, boost::regex("[;][ ]*")); + BOOST_FOREACH(std::string& str, exceptions) { + if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) { + return true; + break; //BOOST_FOREACH + } + } + return false; +} \ No newline at end of file diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index adf417a73..4c23bc78d 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -29,23 +29,30 @@ extern "C" { #include +#include "ExtractorCallbacks.h" #include "ScriptingEnvironment.h" -template class BaseParser : boost::noncopyable { public: + BaseParser(ExtractorCallbacks* em, ScriptingEnvironment& se); virtual ~BaseParser() {} - virtual bool Init() = 0; - virtual void RegisterCallbacks(ExternalMemoryT * externalMemory) = 0; - virtual void RegisterScriptingEnvironment(ScriptingEnvironment & _se) = 0; + virtual bool ReadHeader() = 0; virtual bool Parse() = 0; - void report_errors(lua_State *L, int status) { - if ( status!=0 ) { - std::cerr << "-- " << lua_tostring(L, -1) << std::endl; - lua_pop(L, 1); // remove error message - } - } + inline virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread); + inline virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread); + virtual void report_errors(lua_State *L, int status); + +protected: + virtual void ReadUseRestrictionsSetting(); + virtual void ReadRestrictionExceptions(); + inline virtual bool ShouldIgnoreRestriction(std::string& exception_string); + + ExtractorCallbacks* externalMemory; + ScriptingEnvironment& scriptingEnvironment; + lua_State* luaState; + std::vector restriction_exceptions; + bool use_turn_restrictions; }; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 3280e7e81..de8acad14 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -20,7 +20,7 @@ #include "PBFParser.h" -PBFParser::PBFParser(const char * fileName) : externalMemory(NULL), use_turn_restrictions(true) { +PBFParser::PBFParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char * fileName) : BaseParser( em, se ) { GOOGLE_PROTOBUF_VERIFY_VERSION; //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. @@ -37,43 +37,6 @@ PBFParser::PBFParser(const char * fileName) : externalMemory(NULL), use_turn_res #endif } -void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; -} - -void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - scriptingEnvironment = _se; - - if(0 != luaL_dostring( scriptingEnvironment.getLuaStateForThreadID(0), "return use_turn_restrictions\n")) { - ERR(lua_tostring(scriptingEnvironment.getLuaStateForThreadID(0),-1)<< " occured in scripting block"); - } - if( lua_isboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1) ) { - use_turn_restrictions = lua_toboolean(scriptingEnvironment.getLuaStateForThreadID(0), -1); - } - INFO("Use turn restrictions: " << (use_turn_restrictions ? "yes" : "no")); - - if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) { - //get list of turn restriction exceptions - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(0), - "get_exceptions", - boost::ref(restriction_exceptions_vector) - ); - INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction"); - BOOST_FOREACH(std::string & str, restriction_exceptions_vector) { - INFO("ignoring: " << str); - } - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - } else { - INFO("Found no exceptions to turn restrictions"); - } -} - PBFParser::~PBFParser() { if(input.is_open()) input.close(); @@ -90,7 +53,7 @@ PBFParser::~PBFParser() { #endif } -inline bool PBFParser::Init() { +inline bool PBFParser::ReadHeader() { _ThreadData initData; /** read Header */ if(!readPBFBlobHeader(input, &initData)) { @@ -218,24 +181,9 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) { #pragma omp parallel for schedule ( guided ) for(unsigned i = 0; i < endi_nodes; ++i) { ImportNode &n = nodesToParse[i]; - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "node_function", - boost::ref(n) - ); - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - // catch (...) { - // ERR("Unknown error occurred during PBF dense node parsing!"); - // } + ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); } - BOOST_FOREACH(ImportNode &n, nodesToParse) { if(!externalMemory->nodeFunction(n)) std::cerr << "[PBFParser] dense node not parsed" << std::endl; @@ -249,12 +197,12 @@ inline void PBFParser::parseNode(_ThreadData * ) { inline void PBFParser::parseRelation(_ThreadData * threadData) { //TODO: leave early, if relation is not a restriction //TODO: reuse rawRestriction container - if( use_turn_restrictions==false ) + if( !use_turn_restrictions ) return; const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); for(int i = 0; i < group.relations_size(); ++i ) { - std::string exception_of_restriction_tag; + std::string restriction_exceptions; const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); bool isRestriction = false; bool isOnlyRestriction = false; @@ -272,24 +220,12 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { isOnlyRestriction = true; } if ("except" == key) { - exception_of_restriction_tag = val; - } - } - - //Check if restriction shall be ignored - if(isRestriction && ("" != exception_of_restriction_tag) ) { - //Be warned, this is quadratic work here, but we assume that - //only a few exceptions are actually defined. - std::vector tokenized_exception_tags_of_restriction; - boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*")); - BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) { - if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) { - isRestriction = false; - break; //BOOST_FOREACH - } + restriction_exceptions = val; } } + if( isRestriction && ShouldIgnoreRestriction(restriction_exceptions) ) + isRestriction = false; if(isRestriction) { int64_t lastRef = 0; @@ -368,29 +304,12 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { #pragma omp parallel for schedule ( guided ) for(unsigned i = 0; i < endi_ways; ++i) { ExtractionWay & w = waysToParse[i]; - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), - "way_function", - boost::ref(w), - w.path.size() - ); - - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - // catch (...) { - // ERR("Unknown error!"); - // } + ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); } BOOST_FOREACH(ExtractionWay & w, waysToParse) { - if(!externalMemory->wayFunction(w)) { + if(!externalMemory->wayFunction(w)) std::cerr << "[PBFParser] way not parsed" << std::endl; - } } } diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index e00d64fbc..a483baf19 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -37,11 +37,8 @@ #include "../Util/OpenMPWrapper.h" #include "BaseParser.h" -#include "ExtractorCallbacks.h" -#include "ExtractorStructs.h" -#include "ScriptingEnvironment.h" -class PBFParser : public BaseParser { +class PBFParser : public BaseParser { enum EntityType { TypeNode = 1, @@ -65,13 +62,10 @@ class PBFParser : public BaseParser > threadDataQueue; - ScriptingEnvironment scriptingEnvironment; - - bool use_turn_restrictions; - std::vector restriction_exceptions_vector; + std::fstream input; // the input stream to parse + boost::shared_ptr > threadDataQueue; // ThreadData Queue }; #endif /* PBFPARSER_H_ */ diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 64ef2e25b..b1225cc5c 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -27,42 +27,12 @@ #include "../DataStructures/InputReaderFactory.h" -XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){ +XMLParser::XMLParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char * filename) : BaseParser( em, se ) { WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); inputReader = inputReaderFactory(filename); } -XMLParser::~XMLParser() {} - -void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) { - externalMemory = em; -} - -void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { - myLuaState = _se.getLuaStateForThreadID(0); - if(lua_function_exists(myLuaState, "get_exceptions" )) { - //get list of turn restriction exceptions - try { - luabind::call_function( - myLuaState, - "get_exceptions", - boost::ref(restriction_exceptions_vector) - ); - INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction"); - BOOST_FOREACH(std::string & str, restriction_exceptions_vector) { - INFO(" " << str); - } - } catch (const luabind::error &er) { - lua_State* Ler=er.state(); - report_errors(Ler, -1); - ERR(er.what()); - } - } else { - INFO("Found no exceptions to turn restrictions"); - } -} - -bool XMLParser::Init() { +bool XMLParser::ReadHeader() { return (xmlTextReaderRead( inputReader ) == 1); } bool XMLParser::Parse() { @@ -78,50 +48,18 @@ bool XMLParser::Parse() { continue; if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { - ImportNode n = _ReadXMLNode( ); - /** Pass the unpacked node to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "node_function", - boost::ref(n) - ); - if(!externalMemory->nodeFunction(n)) - std::cerr << "[XMLParser] dense node not parsed" << std::endl; - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML node parsing!"); - } + ImportNode n = _ReadXMLNode(); + ParseNodeInLua( n, luaState ); + + if(!externalMemory->nodeFunction(n)) + std::cerr << "[XMLParser] dense node not parsed" << std::endl; } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { ExtractionWay way = _ReadXMLWay( ); - - /** Pass the unpacked way to the LUA call back **/ - try { - luabind::call_function( - myLuaState, - "way_function", - boost::ref(way), - way.path.size() - ); - if(!externalMemory->wayFunction(way)) { - std::cerr << "[PBFParser] way not parsed" << std::endl; - } - } catch (const luabind::error &er) { - std::cerr << er.what() << std::endl; - lua_State* Ler=er.state(); - report_errors(Ler, -1); - } catch (std::exception & e) { - ERR(e.what()); - } catch (...) { - ERR("Unknown error occurred during XML way parsing!"); - } + ParseWayInLua( way, luaState ); + if(!externalMemory->wayFunction(way)) + std::cerr << "[PBFParser] way not parsed" << std::endl; } if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { _RawRestrictionContainer r = _ReadXMLRestriction(); @@ -138,7 +76,7 @@ bool XMLParser::Parse() { _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { _RawRestrictionContainer restriction; - std::string exception_of_restriction_tag; + std::string exception_string; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { @@ -168,7 +106,7 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { restriction.restriction.flags.isOnly = true; } if ( xmlStrEqual(k, (const xmlChar *) "except") ) { - exception_of_restriction_tag = (const char*) value; + exception_string = (const char*) value; } } @@ -204,19 +142,8 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { } } - //Check if restriction shall be ignored - if( "" != exception_of_restriction_tag ) { - //Be warned, this is quadratic work here, but we assume that - //only a few exceptions are actually defined. - std::vector tokenized_exception_tags_of_restriction; - boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*")); - BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) { - if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) { - restriction.fromWay = UINT_MAX; //workaround to ignore the restriction - break; //BOOST_FOREACH - } - } - } + if( ShouldIgnoreRestriction(exception_string) ) + restriction.fromWay = UINT_MAX; //workaround to ignore the restriction return restriction; } diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index 3bc54825d..cc96e65e1 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -25,28 +25,18 @@ #include "../typedefs.h" #include "BaseParser.h" -#include "ExtractorCallbacks.h" -#include "ScriptingEnvironment.h" -class XMLParser : public BaseParser { +class XMLParser : public BaseParser { public: - XMLParser(const char * filename); - virtual ~XMLParser(); - void RegisterCallbacks(ExtractorCallbacks * em); - void RegisterScriptingEnvironment(ScriptingEnvironment & _se); - bool Init(); + XMLParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char* filename); + bool ReadHeader(); bool Parse(); private: _RawRestrictionContainer _ReadXMLRestriction(); ExtractionWay _ReadXMLWay(); - ImportNode _ReadXMLNode( ); - /* Input Reader */ + ImportNode _ReadXMLNode(); xmlTextReaderPtr inputReader; - ExtractorCallbacks * externalMemory; - lua_State *myLuaState; - - std::vector restriction_exceptions_vector; }; #endif /* XMLPARSER_H_ */ diff --git a/extractor.cpp b/extractor.cpp index 1aa72f83b..fb52961e6 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -94,20 +94,19 @@ int main (int argc, char *argv[]) { stringMap[""] = 0; extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap); - BaseParser * parser; + BaseParser* parser; if(isPBF) { - parser = new PBFParser(argv[1]); + parser = new PBFParser(extractCallBacks, scriptingEnvironment, argv[1]); } else { - parser = new XMLParser(argv[1]); + parser = new XMLParser(extractCallBacks, scriptingEnvironment, argv[1]); } - parser->RegisterCallbacks(extractCallBacks); - parser->RegisterScriptingEnvironment(scriptingEnvironment); - - if(!parser->Init()) + + if(!parser->ReadHeader()) ERR("Parser not initialized!"); + INFO("Parsing in progress.."); double time = get_timestamp(); parser->Parse(); - INFO("parsing finished after " << get_timestamp() - time << " seconds"); + INFO("Parsing finished after " << get_timestamp() - time << " seconds"); externalMemory.PrepareData(outputFileName, restrictionsFileName, amountOfRAM); diff --git a/features/support/data.rb b/features/support/data.rb index 227a962fc..ce6b995c1 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -205,14 +205,15 @@ def write_timestamp end def reprocess + use_pbf = true Dir.chdir TEST_FOLDER do write_osm write_timestamp - convert_osm_to_pbf + convert_osm_to_pbf if use_pbf unless extracted? log_preprocess_info log "== Extracting #{@osm_file}.osm...", :preprocess - unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua" + unless system "../osrm-extract #{@osm_file}.osm#{'.pbf' if use_pbf} 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua" log "*** Exited with code #{$?.exitstatus}.", :preprocess raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}." end From db148741e9077005af106fd8e4b830ba41bbfc0d Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 10 Feb 2013 18:28:04 +0100 Subject: [PATCH 145/161] code cleanup --- Extractor/BaseParser.cpp | 20 +++++----- Extractor/BaseParser.h | 6 +-- Extractor/PBFParser.cpp | 73 +++++++++++++++++++++--------------- Extractor/PBFParser.h | 4 +- Extractor/XMLParser.cpp | 80 ++++++++++++++++++++++++---------------- Extractor/XMLParser.h | 2 +- extractor.cpp | 7 ++-- 7 files changed, 112 insertions(+), 80 deletions(-) diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp index d84ebe034..d57c4c5cf 100644 --- a/Extractor/BaseParser.cpp +++ b/Extractor/BaseParser.cpp @@ -20,15 +20,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "BaseParser.h" -BaseParser::BaseParser(ExtractorCallbacks* em, ScriptingEnvironment& se) : -externalMemory(em), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { +BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) : +externalMemory(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { luaState = se.getLuaStateForThreadID(0); ReadUseRestrictionsSetting(); ReadRestrictionExceptions(); } void BaseParser::ReadUseRestrictionsSetting() { - if(0 != luaL_dostring( luaState, "return use_turn_restrictions\n")) { + if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) { ERR(lua_tostring( luaState,-1)<< " occured in scripting block"); } if( lua_isboolean( luaState, -1) ) { @@ -64,8 +64,8 @@ void BaseParser::ReadRestrictionExceptions() { } } -void BaseParser::report_errors(lua_State *L, int status) { - if ( status!=0 ) { +void BaseParser::report_errors(lua_State *L, const int status) const { + if( 0!=status ) { std::cerr << "-- " << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); // remove error message } @@ -91,22 +91,22 @@ inline void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState } } -inline bool BaseParser::ShouldIgnoreRestriction(std::string& exception_string) { +inline bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const { //should this restriction be ignored? yes if there's an overlap between: - //a) the list of modes in the except tag of the restriction (exception_string), ex: except=bus;bicycle + //a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle //b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle] - if( "" == exception_string ) + if( "" == except_tag_string ) { return false; + } //Be warned, this is quadratic work here, but we assume that //only a few exceptions are actually defined. std::vector exceptions; - boost::algorithm::split_regex(exceptions, exception_string, boost::regex("[;][ ]*")); + boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); BOOST_FOREACH(std::string& str, exceptions) { if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) { return true; - break; //BOOST_FOREACH } } return false; diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index 4c23bc78d..891af320b 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -34,19 +34,19 @@ extern "C" { class BaseParser : boost::noncopyable { public: - BaseParser(ExtractorCallbacks* em, ScriptingEnvironment& se); + BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se); virtual ~BaseParser() {} virtual bool ReadHeader() = 0; virtual bool Parse() = 0; inline virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread); inline virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread); - virtual void report_errors(lua_State *L, int status); + virtual void report_errors(lua_State *L, const int status) const; protected: virtual void ReadUseRestrictionsSetting(); virtual void ReadRestrictionExceptions(); - inline virtual bool ShouldIgnoreRestriction(std::string& exception_string); + inline virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; ExtractorCallbacks* externalMemory; ScriptingEnvironment& scriptingEnvironment; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index de8acad14..30ad1feb6 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -20,7 +20,7 @@ #include "PBFParser.h" -PBFParser::PBFParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char * fileName) : BaseParser( em, se ) { +PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) { GOOGLE_PROTOBUF_VERIFY_VERSION; //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. @@ -38,8 +38,9 @@ PBFParser::PBFParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const cha } PBFParser::~PBFParser() { - if(input.is_open()) + if(input.is_open()) { input.close(); + } // Clean up any leftover ThreadData objects in the queue _ThreadData* td; @@ -69,11 +70,13 @@ inline bool PBFParser::ReadHeader() { for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { const std::string& feature = initData.PBFHeaderBlock.required_features( i ); bool supported = false; - if ( "OsmSchema-V0.6" == feature ) + if ( "OsmSchema-V0.6" == feature ) { supported = true; - else if ( "DenseNodes" == feature ) + } + else if ( "DenseNodes" == feature ) { supported = true; - + } + if ( !supported ) { std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; return false; @@ -91,9 +94,9 @@ inline void PBFParser::ReadData() { _ThreadData *threadData = new _ThreadData(); keepRunning = readNextBlock(input, threadData); - if (keepRunning) + if (keepRunning) { threadDataQueue->push(threadData); - else { + } else { threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered delete threadData; } @@ -104,7 +107,7 @@ inline void PBFParser::ParseData() { while (true) { _ThreadData *threadData; threadDataQueue->wait_and_pop(threadData); - if (threadData == NULL) { + if( NULL==threadData ) { INFO("Parse Data Thread Finished"); threadDataQueue->push(NULL); // Signal end of data for other threads break; @@ -116,14 +119,18 @@ inline void PBFParser::ParseData() { threadData->currentGroupID = i; loadGroup(threadData); - if(threadData->entityTypeIndicator == TypeNode) + if(threadData->entityTypeIndicator == TypeNode) { parseNode(threadData); - if(threadData->entityTypeIndicator == TypeWay) + } + if(threadData->entityTypeIndicator == TypeWay) { parseWay(threadData); - if(threadData->entityTypeIndicator == TypeRelation) + } + if(threadData->entityTypeIndicator == TypeRelation) { parseRelation(threadData); - if(threadData->entityTypeIndicator == TypeDenseNode) + } + if(threadData->entityTypeIndicator == TypeDenseNode) { parseDenseNode(threadData); + } } delete threadData; @@ -164,7 +171,7 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) { n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; while (denseTagIndex < dense.keys_vals_size()) { const int tagValue = dense.keys_vals( denseTagIndex ); - if(tagValue == 0) { + if( 0==tagValue ) { ++denseTagIndex; break; } @@ -197,12 +204,12 @@ inline void PBFParser::parseNode(_ThreadData * ) { inline void PBFParser::parseRelation(_ThreadData * threadData) { //TODO: leave early, if relation is not a restriction //TODO: reuse rawRestriction container - if( !use_turn_restrictions ) - return; - + if( !use_turn_restrictions ) { + return; + } const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); for(int i = 0; i < group.relations_size(); ++i ) { - std::string restriction_exceptions; + std::string except_tag_string; const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); bool isRestriction = false; bool isOnlyRestriction = false; @@ -210,22 +217,25 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); if ("type" == key) { - if( "restriction" == val) + if( "restriction" == val) { isRestriction = true; - else + } else { break; + } } if ("restriction" == key) { - if(val.find("only_") == 0) + if(val.find("only_") == 0) { isOnlyRestriction = true; + } } if ("except" == key) { - restriction_exceptions = val; + except_tag_string = val; } } - if( isRestriction && ShouldIgnoreRestriction(restriction_exceptions) ) - isRestriction = false; + if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) { + isRestriction = false; + } if(isRestriction) { int64_t lastRef = 0; @@ -240,11 +250,13 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { switch(inputRelation.types(rolesIndex)) { case 0: //node - if("from" == role || "to" == role) //Only via should be a node + if("from" == role || "to" == role) { //Only via should be a node continue; + } assert("via" == role); - if(UINT_MAX != currentRestrictionContainer.viaNode) + if(UINT_MAX != currentRestrictionContainer.viaNode) { currentRestrictionContainer.viaNode = UINT_MAX; + } assert(UINT_MAX == currentRestrictionContainer.viaNode); currentRestrictionContainer.restriction.viaNode = lastRef; break; @@ -272,8 +284,9 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { break; } } - if(!externalMemory->restrictionFunction(currentRestrictionContainer)) + if(!externalMemory->restrictionFunction(currentRestrictionContainer)) { std::cerr << "[PBFParser] relation not parsed" << std::endl; + } } } } @@ -406,9 +419,10 @@ inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) { } inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) { - if(stream.eof()) + if(stream.eof()) { return false; - + } + const int size = threadData->PBFBlobHeader.datasize(); if ( size < 0 || size > MAX_BLOB_SIZE ) { std::cerr << "[error] invalid Blob size:" << size << std::endl; @@ -436,8 +450,9 @@ inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) return false; } } else if ( threadData->PBFBlob.has_lzma_data() ) { - if ( !unpackLZMA(stream, threadData) ) + if ( !unpackLZMA(stream, threadData) ) { std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; + } delete[] data; return false; } else { diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index a483baf19..587fbc96c 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -62,7 +62,7 @@ class PBFParser : public BaseParser { }; public: - PBFParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char * fileName); + PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se); virtual ~PBFParser(); inline bool ReadHeader(); @@ -95,7 +95,7 @@ private: #endif std::fstream input; // the input stream to parse - boost::shared_ptr > threadDataQueue; // ThreadData Queue + boost::shared_ptr > threadDataQueue; }; #endif /* PBFPARSER_H_ */ diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index b1225cc5c..f28440d36 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -27,7 +27,7 @@ #include "../DataStructures/InputReaderFactory.h" -XMLParser::XMLParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char * filename) : BaseParser( em, se ) { +XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) { WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); inputReader = inputReaderFactory(filename); } @@ -40,16 +40,18 @@ bool XMLParser::Parse() { const int type = xmlTextReaderNodeType( inputReader ); //1 is Element - if ( type != 1 ) + if ( type != 1 ) { continue; - + } + xmlChar* currentName = xmlTextReaderName( inputReader ); - if ( currentName == NULL ) + if ( currentName == NULL ) { continue; - + } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { ImportNode n = _ReadXMLNode(); - ParseNodeInLua( n, luaState ); + ParseNodeInLua( n, luaState ); if(!externalMemory->nodeFunction(n)) std::cerr << "[XMLParser] dense node not parsed" << std::endl; @@ -57,7 +59,7 @@ bool XMLParser::Parse() { if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { ExtractionWay way = _ReadXMLWay( ); - ParseWayInLua( way, luaState ); + ParseWayInLua( way, luaState ); if(!externalMemory->wayFunction(way)) std::cerr << "[PBFParser] way not parsed" << std::endl; } @@ -75,19 +77,20 @@ bool XMLParser::Parse() { } _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { - _RawRestrictionContainer restriction; - std::string exception_string; + _RawRestrictionContainer restriction; + std::string except_tag_string; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) + if ( childType != 1 && childType != 15 ) { continue; + } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) + if ( childName == NULL ) { continue; - + } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { xmlFree( childName ); break; @@ -102,18 +105,21 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); if ( k != NULL && value != NULL ) { if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ - if(0 == std::string((const char *) value).find("only_")) + if(0 == std::string((const char *) value).find("only_")) { restriction.restriction.flags.isOnly = true; + } } if ( xmlStrEqual(k, (const xmlChar *) "except") ) { - exception_string = (const char*) value; + except_tag_string = (const char*) value; } } - if ( k != NULL ) + if ( k != NULL ) { xmlFree( k ); - if ( value != NULL ) + } + if ( value != NULL ) { xmlFree( value ); + } } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); if ( ref != NULL ) { @@ -130,21 +136,24 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { restriction.restriction.viaNode = atoi((const char*) ref); } - if(NULL != type) + if(NULL != type) { xmlFree( type ); - if(NULL != role) + } + if(NULL != role) { xmlFree( role ); - if(NULL != ref) + } + if(NULL != ref) { xmlFree( ref ); + } } } xmlFree( childName ); } } - if( ShouldIgnoreRestriction(exception_string) ) - restriction.fromWay = UINT_MAX; //workaround to ignore the restriction - + if( ShouldIgnoreRestriction(except_tag_string) ) { + restriction.fromWay = UINT_MAX; //workaround to ignore the restriction + } return restriction; } @@ -154,12 +163,14 @@ ExtractionWay XMLParser::_ReadXMLWay() { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); - if ( childType != 1 && childType != 15 ) + if ( childType != 1 && childType != 15 ) { continue; + } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) + if ( childName == NULL ) { continue; + } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); @@ -176,15 +187,16 @@ ExtractionWay XMLParser::_ReadXMLWay() { if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); - // cout << "->k=" << k << ", v=" << value << endl; + // cout << "->k=" << k << ", v=" << value << endl; if ( k != NULL && value != NULL ) { - way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); } - if ( k != NULL ) + if ( k != NULL ) { xmlFree( k ); - if ( value != NULL ) + } + if ( value != NULL ) { xmlFree( value ); + } } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); if ( ref != NULL ) { @@ -222,12 +234,14 @@ ImportNode XMLParser::_ReadXMLNode() { while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); // 1 = Element, 15 = EndElement - if ( childType != 1 && childType != 15 ) + if ( childType != 1 && childType != 15 ) { continue; + } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); - if ( childName == NULL ) + if ( childName == NULL ) { continue; + } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { xmlFree( childName ); @@ -244,10 +258,12 @@ ImportNode XMLParser::_ReadXMLNode() { if ( k != NULL && value != NULL ) { node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); } - if ( k != NULL ) + if ( k != NULL ) { xmlFree( k ); - if ( value != NULL ) + } + if ( value != NULL ) { xmlFree( value ); + } } xmlFree( childName ); diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index cc96e65e1..a2af2fb86 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -28,7 +28,7 @@ class XMLParser : public BaseParser { public: - XMLParser(ExtractorCallbacks* em, ScriptingEnvironment& se, const char* filename); + XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se); bool ReadHeader(); bool Parse(); diff --git a/extractor.cpp b/extractor.cpp index fb52961e6..4912c9b67 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -96,13 +96,14 @@ int main (int argc, char *argv[]) { extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap); BaseParser* parser; if(isPBF) { - parser = new PBFParser(extractCallBacks, scriptingEnvironment, argv[1]); + parser = new PBFParser(argv[1], extractCallBacks, scriptingEnvironment); } else { - parser = new XMLParser(extractCallBacks, scriptingEnvironment, argv[1]); + parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment); } - if(!parser->ReadHeader()) + if(!parser->ReadHeader()) { ERR("Parser not initialized!"); + } INFO("Parsing in progress.."); double time = get_timestamp(); parser->Parse(); From 313b93169dc4a15bb9f6e03187dca0227a51423b Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 11 Feb 2013 10:05:53 +0100 Subject: [PATCH 146/161] turn off turn restrictions for bicycle and foot, update tests --- features/bicycle/restrictions.feature | 36 +++++++++++++-------------- profiles/bicycle.lua | 2 +- profiles/foot.lua | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index 27c5c353e..2d5fa40c5 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -1,6 +1,6 @@ @routing @bicycle @restrictions Feature: Bike - Turn restrictions - Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction + Ignore turn restrictions on bicycle, since you always become a temporary pedestrian. Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes. Background: @@ -26,7 +26,7 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | + | s | w | sj,wj | | s | n | sj,nj | | s | e | sj,ej | @@ -52,7 +52,7 @@ Feature: Bike - Turn restrictions | from | to | route | | s | w | sj,wj | | s | n | sj,nj | - | s | e | | + | s | e | sj,ej | @no_turning Scenario: Bike - No u-turn @@ -74,7 +74,7 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | + | s | w | sj,wj | | s | n | sj,nj | | s | e | sj,ej | @@ -98,7 +98,7 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | + | s | w | sj,wj | | s | n | sj,nj | | s | e | sj,ej | @@ -123,8 +123,8 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | | s | w | sj,wj | - | s | n | | - | s | e | | + | s | n | sj,nj | + | s | e | sj,ej | @only_turning Scenario: Bike - Only right turn @@ -146,8 +146,8 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | - | s | n | | + | s | w | sj,wj | + | s | n | sj,nj | | s | e | sj,ej | @only_turning @@ -170,9 +170,9 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | + | s | w | sj,wj | | s | n | sj,nj | - | s | e | | + | s | e | sj,ej | @no_turning Scenario: Bike - Handle any only_* restriction @@ -194,9 +194,9 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | w | | + | s | w | sj,wj | | s | n | sj,nj | - | s | e | | + | s | e | sj,ej | @except Scenario: Bike - Except tag and on no_ restrictions @@ -224,8 +224,8 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | | s | a | sj,aj | - | s | b | | - | s | c | | + | s | b | sj,bj | + | s | c | sj,cj | | s | d | sj,dj | @except @@ -281,9 +281,9 @@ Feature: Bike - Turn restrictions When I route I should get | from | to | route | - | s | a | | + | s | a | sj,ja | | s | b | sj,jb | | s | c | sj,jc | | s | d | sj,jd | - | s | e | | - | s | f | | + | s | e | sj,je | + | s | f | sj,jf | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index cb07ea6fb..9e122c354 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -72,7 +72,7 @@ use_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 - +use_turn_restrictions = false -- End of globals function get_exceptions(vector) diff --git a/profiles/foot.lua b/profiles/foot.lua index e85cc2fd0..fb0dee8db 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -41,7 +41,7 @@ use_restrictions = false ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 2 - +use_turn_restrictions = false -- End of globals function get_exceptions(vector) From ae8e51074e78ae70ede0cbb0054f73a8c2029468 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 22 Feb 2013 14:31:49 +0100 Subject: [PATCH 147/161] Removing superflous inline statements --- Extractor/BaseParser.cpp | 8 ++++---- Extractor/BaseParser.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp index d57c4c5cf..14c6dd24d 100644 --- a/Extractor/BaseParser.cpp +++ b/Extractor/BaseParser.cpp @@ -71,7 +71,7 @@ void BaseParser::report_errors(lua_State *L, const int status) const { } } -inline void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { +void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { try { luabind::call_function( localLuaState, "node_function", boost::ref(n) ); } catch (const luabind::error &er) { @@ -81,7 +81,7 @@ inline void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) } } -inline void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) { +void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) { try { luabind::call_function( localLuaState, "way_function", boost::ref(w), w.path.size() ); } catch (const luabind::error &er) { @@ -91,7 +91,7 @@ inline void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState } } -inline bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const { +bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const { //should this restriction be ignored? yes if there's an overlap between: //a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle //b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle] @@ -110,4 +110,4 @@ inline bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_st } } return false; -} \ No newline at end of file +} diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index 891af320b..f4904fc01 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -39,14 +39,14 @@ public: virtual bool ReadHeader() = 0; virtual bool Parse() = 0; - inline virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread); - inline virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread); + virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread); + virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread); virtual void report_errors(lua_State *L, const int status) const; protected: virtual void ReadUseRestrictionsSetting(); virtual void ReadRestrictionExceptions(); - inline virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; + virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; ExtractorCallbacks* externalMemory; ScriptingEnvironment& scriptingEnvironment; From cc55b016e985c07c654c6c7aaf790e8361e0cb91 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 15 Feb 2013 17:02:49 +0100 Subject: [PATCH 148/161] don't push against oneway flow on roundabout. fixes #591 --- features/bicycle/pushing.feature | 6 ++++++ profiles/bicycle.lua | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 8e2ca3052..1c6919706 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -79,3 +79,9 @@ Feature: Bike - Accessability of different way types | construction | | | | | construction | yes | | | | construction | | yes | | + + @roundabout + Scenario: Bike - Don't push bikes against oneway flow on roundabouts + Then routability should be + | junction | forw | backw | + | roundabout | x | | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 9e122c354..03ecb66e4 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -264,12 +264,14 @@ function way_function (way, numberOfNodesInWay) -- pushing bikes if bicycle_speeds[highway] or pedestrian_speeds[highway] then if foot ~= 'no' then - if way.direction == Way.oneway then - way.backward_speed = walking_speed - elseif way.direction == Way.opposite then - way.backward_speed = walking_speed - way.speed = way.speed - end + if junction ~= "roundabout" then + if way.direction == Way.oneway then + way.backward_speed = walking_speed + elseif way.direction == Way.opposite then + way.backward_speed = walking_speed + way.speed = way.speed + end + end end if way.backward_speed == way.speed then -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal From 81a05c89e48c9d241a8357dee528313da1ff26ea Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 11 Feb 2013 11:02:21 +0100 Subject: [PATCH 149/161] update bike speeds --- profiles/bicycle.lua | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 03ecb66e4..4da2f2973 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -10,25 +10,25 @@ cycleway_tags = {["track"]=true,["lane"]=true,["opposite"]=true,["opposite_lane" service_tag_restricted = { ["parking_aisle"] = true } restriction_exception_tags = { "bicycle", "vehicle", "access" } -default_speed = 16 +default_speed = 15 -walking_speed = 4 +walking_speed = 6 bicycle_speeds = { - ["cycleway"] = 18, - ["primary"] = 17, - ["primary_link"] = 17, - ["secondary"] = 18, - ["secondary_link"] = 18, - ["tertiary"] = 18, - ["tertiary_link"] = 18, - ["residential"] = 18, - ["unclassified"] = 16, - ["living_street"] = 16, - ["road"] = 16, - ["service"] = 16, - ["track"] = 13, - ["path"] = 13 + ["cycleway"] = default_speed, + ["primary"] = default_speed, + ["primary_link"] = default_speed, + ["secondary"] = default_speed, + ["secondary_link"] = default_speed, + ["tertiary"] = default_speed, + ["tertiary_link"] = default_speed, + ["residential"] = default_speed, + ["unclassified"] = default_speed, + ["living_street"] = default_speed, + ["road"] = default_speed, + ["service"] = default_speed, + ["track"] = 12, + ["path"] = 12 --["footway"] = 12, --["pedestrian"] = 12, } @@ -70,7 +70,7 @@ obey_oneway = true obey_bollards = false use_restrictions = true ignore_areas = true -- future feature -traffic_signal_penalty = 2 +traffic_signal_penalty = 5 u_turn_penalty = 20 use_turn_restrictions = false -- End of globals From b051f715e62ca7b9192e743f2390baf0f265b2f9 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 11 Feb 2013 11:03:24 +0100 Subject: [PATCH 150/161] add 'no' to barrier whitelist in bike profile --- profiles/bicycle.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 4da2f2973..f6609d097 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,7 +1,7 @@ require("lib/access") -- 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} +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_restricted = { ["destination"] = true, ["delivery"] = true } From f88a4baf796cbaa2028360eea9f324fd4cd9315d Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 19 Feb 2013 08:54:23 +0100 Subject: [PATCH 151/161] update bike tests --- features/bicycle/maxspeed.feature | 24 ++++++++++++------------ features/bicycle/pushing.feature | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index b02fe4e33..9924f5596 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -7,35 +7,35 @@ Feature: Bike - Max speed restrictions Scenario: Bicycle - Respect maxspeeds when lower that way type speed Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | + | residential | | 49s ~10% | | residential | 10 | 72s ~10% | Scenario: Bicycle - Ignore maxspeed when higher than way speed Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | - | residential | 80 | 40s ~10% | + | residential | | 49s ~10% | + | residential | 80 | 49s ~10% | @todo Scenario: Bicycle - Maxspeed formats Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | + | residential | | 49s ~10% | | residential | 5 | 144s ~10% | | residential | 5mph | 90s ~10% | | residential | 5 mph | 90s ~10% | | residential | 5MPH | 90s ~10% | | residential | 5 MPH | 90s ~10% | - | trunk | 5unknown | 40s ~10% | - | trunk | 5 unknown | 40s ~10% | + | trunk | 5unknown | 49s ~10% | + | trunk | 5 unknown | 49s ~10% | @todo Scenario: Bicycle - Maxspeed special tags Then routability should be | highway | maxspeed | bothw | - | residential | | 40s ~10% | - | residential | none | 40s ~10% | - | residential | signals | 40s ~10% | + | residential | | 49s ~10% | + | residential | none | 49s ~10% | + | residential | signals | 49s ~10% | Scenario: Bike - Do not use maxspeed when higher that way type speed Given the node map @@ -48,13 +48,13 @@ Feature: Bike - Max speed restrictions When I route I should get | from | to | route | time | - | a | b | ab | 20s ~5% | - | b | c | bc | 20s ~5% | + | a | b | ab | 24s ~5% | + | b | c | bc | 24s ~5% | Scenario: Bike - Forward/backward maxspeed Given the shortcuts | key | value | - | bike | 43s ~10% | + | bike | 49s ~10% | | run | 73s ~10% | | walk | 145s ~10% | | snail | 720s ~10% | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 1c6919706..169d340e3 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -5,8 +5,8 @@ Feature: Bike - Accessability of different way types Given the profile "bicycle" Given the shortcuts | key | value | - | bike | 40s ~20% | - | foot | 180s ~20% | + | bike | 49s ~20% | + | foot | 121s ~20% | Scenario: Bike - Pushing bikes on pedestrian-only ways Then routability should be From c6840496c0cc60c49d9f5d60589dcc1fbe35ff2a Mon Sep 17 00:00:00 2001 From: drxzcl Date: Wed, 13 Feb 2013 09:39:45 +0100 Subject: [PATCH 152/161] Add basic CORS headers to allow cross-site access. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ¨Access-Control-Allow-Origin: *¨ to the HTTP headers of all replies. This allows use in a cross-origin AJAX situation. In compliance with the recommendations of section 4.2 of RFC2616, the header is added before the existing entity headers. --- Server/BasicDatastructures.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h index e87656975..71e3ac996 100644 --- a/Server/BasicDatastructures.h +++ b/Server/BasicDatastructures.h @@ -139,11 +139,13 @@ Reply Reply::stockReply(Reply::status_type status) { Reply rep; rep.status = status; rep.content = ToString(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; + rep.headers.resize(3); + rep.headers[0].name = "Access-Control-Allow-Origin"; + rep.headers[0].value = "*"; + rep.headers[1].name = "Content-Length"; + rep.headers[1].value = boost::lexical_cast(rep.content.size()); + rep.headers[2].name = "Content-Type"; + rep.headers[2].value = "text/html"; return rep; } } // namespace http From 0399022d253f04e0c6d69b76f50112e52a2f0732 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 23 Feb 2013 08:53:42 +0100 Subject: [PATCH 153/161] update turn instruction test --- features/testbot/turns.feature | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature index 34a0c9199..f63a944d1 100644 --- a/features/testbot/turns.feature +++ b/features/testbot/turns.feature @@ -97,13 +97,14 @@ Feature: Turn directions/codes | g | c | xg,xc | head,right,destination | | g | e | xg,xe | head,sharp_right,destination | + @todo Scenario: Skadestuevej, København https://github.com/DennisOSRM/Project-OSRM/issues/532 Given the node locations | node | lat | lon | - | a | 55.68679 | 12.52360 | - | b | 55.68745 | 12.52407 | - | c | 55.68720 | 12.52509 | + | a | 55.68740 | 12.52430 | + | b | 55.68745 | 12.52409 | + | c | 55.68711 | 12.52383 | And the ways | nodes | @@ -111,5 +112,5 @@ Feature: Turn directions/codes | bc | When I route I should get - | from | to | route | turns | - | a | c | ab,bc | head,right,destination | + | from | to | route | turns | + | a | c | ab,bc | head,left,destination | From 3c8dd85966484b10eada04998dd1103f1f18bab5 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 23 Feb 2013 13:53:06 +0100 Subject: [PATCH 154/161] respect use_restricions in xml import --- Extractor/XMLParser.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index f28440d36..df251455e 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -63,11 +63,13 @@ bool XMLParser::Parse() { if(!externalMemory->wayFunction(way)) std::cerr << "[PBFParser] way not parsed" << std::endl; } - if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { - _RawRestrictionContainer r = _ReadXMLRestriction(); - if(r.fromWay != UINT_MAX) { - if(!externalMemory->restrictionFunction(r)) { - std::cerr << "[XMLParser] restriction not parsed" << std::endl; + if( use_turn_restrictions ) { + if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { + _RawRestrictionContainer r = _ReadXMLRestriction(); + if(r.fromWay != UINT_MAX) { + if(!externalMemory->restrictionFunction(r)) { + std::cerr << "[XMLParser] restriction not parsed" << std::endl; + } } } } From c4693602efca471c2f0f615705b86cf51f40f8fa Mon Sep 17 00:00:00 2001 From: Project OSRM Date: Mon, 25 Feb 2013 14:52:35 +0100 Subject: [PATCH 155/161] Adding geometry to production rules --- Server/APIGrammar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h index b24a1b206..3b8794185 100644 --- a/Server/APIGrammar.h +++ b/Server/APIGrammar.h @@ -33,7 +33,7 @@ template struct APIGrammar : qi::grammar { APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) { api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query); - query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | alt_route | old_API) ) ; + query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ; zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; From ea83231da5284e189254466b9ce70b2f009a2b2f Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 25 Feb 2013 18:47:17 +0100 Subject: [PATCH 156/161] Fixing incorrect initialization of hash function --- DataStructures/XORFastHash.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/DataStructures/XORFastHash.h b/DataStructures/XORFastHash.h index e90de23df..3f1b29460 100644 --- a/DataStructures/XORFastHash.h +++ b/DataStructures/XORFastHash.h @@ -46,10 +46,10 @@ class XORFastHash { //65k entries std::vector table2; public: XORFastHash() { - table1.resize(2 << 16); - table2.resize(2 << 16); - for(unsigned i = 0; i < (2 << 16); ++i) { - table1[i] = i; table2[i]; + table1.resize(1 << 16); + table2.resize(1 << 16); + for(unsigned i = 0; i < (1 << 16); ++i) { + table1[i] = i; table2[i] = i; } std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table2.begin(), table2.end()); @@ -75,8 +75,8 @@ public: table3.resize(1 << 8); table4.resize(1 << 8); for(unsigned i = 0; i < (1 << 8); ++i) { - table1[i] = i; table2[i]; - table3[i] = i; table4[i]; + table1[i] = i; table2[i] = i; + table3[i] = i; table4[i] = i; } std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table2.begin(), table2.end()); From af5f2f85da2bef8f82799a914dc2831ad051f966 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 26 Feb 2013 09:57:29 +0100 Subject: [PATCH 157/161] Workaround for failing tests --- DataStructures/XORFastHash.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DataStructures/XORFastHash.h b/DataStructures/XORFastHash.h index 3f1b29460..c3c14702b 100644 --- a/DataStructures/XORFastHash.h +++ b/DataStructures/XORFastHash.h @@ -46,9 +46,9 @@ class XORFastHash { //65k entries std::vector table2; public: XORFastHash() { - table1.resize(1 << 16); - table2.resize(1 << 16); - for(unsigned i = 0; i < (1 << 16); ++i) { + table1.resize(2 << 16); + table2.resize(2 << 16); + for(unsigned i = 0; i < (2 << 16); ++i) { table1[i] = i; table2[i] = i; } std::random_shuffle(table1.begin(), table1.end()); From 53af4ee39f391082e2670691015ed857326de178 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 27 Feb 2013 17:36:44 +0100 Subject: [PATCH 158/161] Cleaning of several regressions in the parsing code. --- Extractor/BaseParser.cpp | 9 +- Extractor/BaseParser.h | 2 +- Extractor/ExtractorCallbacks.cpp | 59 ++++----- Extractor/ExtractorCallbacks.h | 6 +- Extractor/PBFParser.cpp | 59 +++++---- Extractor/XMLParser.cpp | 13 +- profile.lua | 220 ++++++++++++++++++++++++++++++- profiles/bicycle.lua | 7 +- profiles/car.lua | 8 +- profiles/foot.lua | 7 +- profiles/testbot.lua | 7 +- 11 files changed, 297 insertions(+), 100 deletions(-) mode change 120000 => 100644 profile.lua diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp index 14c6dd24d..6981e9570 100644 --- a/Extractor/BaseParser.cpp +++ b/Extractor/BaseParser.cpp @@ -21,7 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "BaseParser.h" BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) : -externalMemory(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { +extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { luaState = se.getLuaStateForThreadID(0); ReadUseRestrictionsSetting(); ReadRestrictionExceptions(); @@ -73,7 +73,7 @@ void BaseParser::report_errors(lua_State *L, const int status) const { void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { try { - luabind::call_function( localLuaState, "node_function", boost::ref(n) ); + luabind::call_function( localLuaState, "node_function", boost::ref(n) ); } catch (const luabind::error &er) { lua_State* Ler=er.state(); report_errors(Ler, -1); @@ -82,8 +82,11 @@ void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { } void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) { + if(2 > w.path.size()) { + return; + } try { - luabind::call_function( localLuaState, "way_function", boost::ref(w), w.path.size() ); + luabind::call_function( localLuaState, "way_function", boost::ref(w) ); } catch (const luabind::error &er) { lua_State* Ler=er.state(); report_errors(Ler, -1); diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index f4904fc01..6a19efa07 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -48,7 +48,7 @@ protected: virtual void ReadRestrictionExceptions(); virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; - ExtractorCallbacks* externalMemory; + ExtractorCallbacks* extractor_callbacks; ScriptingEnvironment& scriptingEnvironment; lua_State* luaState; std::vector restriction_exceptions; diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 5da2bce4f..c8b5fc1aa 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -48,58 +48,54 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * s stringMap = strMap; } -ExtractorCallbacks::~ExtractorCallbacks() { -} +ExtractorCallbacks::~ExtractorCallbacks() { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::nodeFunction(_Node &n) { - if(n.lat <= 85*100000 && n.lat >= -85*100000) +void ExtractorCallbacks::nodeFunction(const _Node &n) { + if(n.lat <= 85*100000 && n.lat >= -85*100000) { externalMemory->allNodes.push_back(n); - return true; + } } -bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { +bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) { externalMemory->restrictionsVector.push_back(r); return true; } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { - if ( parsed_way.speed > 0 || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile - if(parsed_way.id == UINT_MAX){ - WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); - return true; - } - //Get the unique identifier for the street name - const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); - if(string_map_iterator == stringMap->end()) { - parsed_way.nameID = externalMemory->nameVector.size(); - externalMemory->nameVector.push_back(parsed_way.name); - stringMap->insert(StringMap::value_type(parsed_way.name, parsed_way.nameID)); - } else { - parsed_way.nameID = string_map_iterator->second; +void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { + if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile + if(UINT_MAX == parsed_way.id){ + DEBUG("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); + return; } - if(parsed_way.duration > 0) { + if(0 < parsed_way.duration) { //TODO: iterate all way segments and set duration corresponding to the length of each segment parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1); } - if(fabs(-1. - parsed_way.speed) < FLT_EPSILON){ - WARN("found way with bogus speed, id: " << parsed_way.id); - return true; - } - if(parsed_way.id == UINT_MAX) { - WARN("found way with unknown type: " << parsed_way.id); - return true; + if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){ + DEBUG("found way with bogus speed, id: " << parsed_way.id); + return; } - if ( parsed_way.direction == ExtractionWay::opposite ){ + //Get the unique identifier for the street name + const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); + if(stringMap->end() == string_map_iterator) { + parsed_way.nameID = externalMemory->nameVector.size(); + externalMemory->nameVector.push_back(parsed_way.name); + stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID)); + } else { + parsed_way.nameID = string_map_iterator->second; + } + + if(ExtractionWay::opposite == parsed_way.direction) { std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); parsed_way.direction = ExtractionWay::oneway; } - bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); + const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( @@ -122,7 +118,7 @@ bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { //The following information is needed to identify start and end segments of restrictions externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); - if ( split_bidirectional_edge) { //Only true if the way should be split + if(split_bidirectional_edge) { //Only true if the way should be split std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->allEdges.push_back( @@ -143,5 +139,4 @@ bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); } } - return true; } diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h index 3ddbbe841..4293d1330 100644 --- a/Extractor/ExtractorCallbacks.h +++ b/Extractor/ExtractorCallbacks.h @@ -45,12 +45,12 @@ public: ~ExtractorCallbacks(); /** warning: caller needs to take care of synchronization! */ - bool nodeFunction(_Node &n); + void nodeFunction(const _Node &n); - bool restrictionFunction(_RawRestrictionContainer &r); + bool restrictionFunction(const _RawRestrictionContainer &r); /** warning: caller needs to take care of synchronization! */ - bool wayFunction(ExtractionWay &w); + void wayFunction(ExtractionWay &w); }; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 30ad1feb6..2f343ca9f 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -160,14 +160,16 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) { int m_lastDenseLongitude = 0; ImportNode n; - std::vector nodesToParse; - for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { + std::vector extracted_nodes_vector; + const int number_of_nodes = dense.id_size(); + extracted_nodes_vector.reserve(number_of_nodes); + for(int i = 0; i < number_of_nodes; ++i) { n.Clear(); m_lastDenseID += dense.id( i ); m_lastDenseLatitude += dense.lat( i ); m_lastDenseLongitude += dense.lon( i ); n.id = m_lastDenseID; - n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; + n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO; n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; while (denseTagIndex < dense.keys_vals_size()) { const int tagValue = dense.keys_vals( denseTagIndex ); @@ -181,20 +183,18 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) { n.keyVals.Add(key, value); denseTagIndex += 2; } - nodesToParse.push_back(n); + extracted_nodes_vector.push_back(n); } - unsigned endi_nodes = nodesToParse.size(); #pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_nodes; ++i) { - ImportNode &n = nodesToParse[i]; - ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); - } + for(int i = 0; i < number_of_nodes; ++i) { + ImportNode &n = extracted_nodes_vector[i]; + ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); + } - BOOST_FOREACH(ImportNode &n, nodesToParse) { - if(!externalMemory->nodeFunction(n)) - std::cerr << "[PBFParser] dense node not parsed" << std::endl; - } + BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) { + extractor_callbacks->nodeFunction(n); + } } inline void PBFParser::parseNode(_ThreadData * ) { @@ -234,7 +234,7 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { } if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) { - isRestriction = false; + continue; } if(isRestriction) { @@ -284,7 +284,7 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { break; } } - if(!externalMemory->restrictionFunction(currentRestrictionContainer)) { + if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) { std::cerr << "[PBFParser] relation not parsed" << std::endl; } } @@ -293,37 +293,38 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { inline void PBFParser::parseWay(_ThreadData * threadData) { ExtractionWay w; - std::vector waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); - for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { + std::vector waysToParse; + const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); + waysToParse.reserve(number_of_ways); + for(int i = 0; i < number_of_ways; ++i) { w.Clear(); const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); w.id = inputWay.id(); unsigned pathNode(0); - for(int i = 0; i < inputWay.refs_size(); ++i) { + const int number_of_referenced_nodes = inputWay.refs_size(); + for(int i = 0; i < number_of_referenced_nodes; ++i) { pathNode += inputWay.refs(i); w.path.push_back(pathNode); } assert(inputWay.keys_size() == inputWay.vals_size()); - for(int i = 0; i < inputWay.keys_size(); ++i) { + const int number_of_keys = inputWay.keys_size(); + for(int i = 0; i < number_of_keys; ++i) { const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); w.keyVals.Add(key, val); } - waysToParse.push_back(w); } - unsigned endi_ways = waysToParse.size(); #pragma omp parallel for schedule ( guided ) - for(unsigned i = 0; i < endi_ways; ++i) { - ExtractionWay & w = waysToParse[i]; - ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); - } + for(int i = 0; i < number_of_ways; ++i) { + ExtractionWay & w = waysToParse[i]; + ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); + } - BOOST_FOREACH(ExtractionWay & w, waysToParse) { - if(!externalMemory->wayFunction(w)) - std::cerr << "[PBFParser] way not parsed" << std::endl; - } + BOOST_FOREACH(ExtractionWay & w, waysToParse) { + extractor_callbacks->wayFunction(w); + } } inline void PBFParser::loadGroup(_ThreadData * threadData) { diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index df251455e..fa810a702 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -52,22 +52,23 @@ bool XMLParser::Parse() { if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { ImportNode n = _ReadXMLNode(); ParseNodeInLua( n, luaState ); - - if(!externalMemory->nodeFunction(n)) - std::cerr << "[XMLParser] dense node not parsed" << std::endl; + extractor_callbacks->nodeFunction(n); +// if(!extractor_callbacks->nodeFunction(n)) +// std::cerr << "[XMLParser] dense node not parsed" << std::endl; } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { ExtractionWay way = _ReadXMLWay( ); ParseWayInLua( way, luaState ); - if(!externalMemory->wayFunction(way)) - std::cerr << "[PBFParser] way not parsed" << std::endl; + extractor_callbacks->wayFunction(way); +// if(!extractor_callbacks->wayFunction(way)) +// std::cerr << "[PBFParser] way not parsed" << std::endl; } if( use_turn_restrictions ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { _RawRestrictionContainer r = _ReadXMLRestriction(); if(r.fromWay != UINT_MAX) { - if(!externalMemory->restrictionFunction(r)) { + if(!extractor_callbacks->restrictionFunction(r)) { std::cerr << "[XMLParser] restriction not parsed" << std::endl; } } diff --git a/profile.lua b/profile.lua deleted file mode 120000 index bad7e6bb5..000000000 --- a/profile.lua +++ /dev/null @@ -1 +0,0 @@ -profiles/car.lua \ No newline at end of file diff --git a/profile.lua b/profile.lua new file mode 100644 index 000000000..33a7247d6 --- /dev/null +++ b/profile.lua @@ -0,0 +1,219 @@ +-- Begin of globals +require("lib/access") + +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = 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 } +access_tag_restricted = { ["destination"] = true, ["delivery"] = true } +access_tags = { "motorcar", "motor_vehicle", "vehicle" } +access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } +service_tag_restricted = { ["parking_aisle"] = true } +ignore_in_grid = { ["ferry"] = true } +restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } + +speed_profile = { + ["motorway"] = 90, + ["motorway_link"] = 75, + ["trunk"] = 85, + ["trunk_link"] = 70, + ["primary"] = 65, + ["primary_link"] = 60, + ["secondary"] = 55, + ["secondary_link"] = 50, + ["tertiary"] = 40, + ["tertiary_link"] = 30, + ["unclassified"] = 25, + ["residential"] = 25, + ["living_street"] = 10, + ["service"] = 15, +-- ["track"] = 5, + ["ferry"] = 5, + ["shuttle_train"] = 10, + ["default"] = 50 +} + +take_minimum_of_speeds = false +obey_oneway = true +obey_bollards = true +use_restrictions = true +ignore_areas = true -- future feature +traffic_signal_penalty = 2 +u_turn_penalty = 20 + +-- End of globals + +function get_exceptions(vector) + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end + +local function parse_maxspeed(source) + if source == nil then + return 0 + end + local n = tonumber(source:match("%d*")) + if n == nil then + n = 0 + end + if string.match(source, "mph") or string.match(source, "mp/h") then + n = (n*1609)/1000; + end + return math.abs(n) +end + +function node_function (node) + local barrier = node.tags:Find ("barrier") + local access = Access.find_access_tag(node, access_tags_hierachy) + local traffic_signal = node.tags:Find("highway") + + --flag node if it carries a traffic light + + if traffic_signal == "traffic_signals" then + node.traffic_light = true; + end + + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + return + else + node.bollard = true + end + end + return 1 +end + + +function way_function (way) + -- First, get the properties of each way that we come across + local highway = way.tags:Find("highway") + local name = way.tags:Find("name") + local ref = way.tags:Find("ref") + local junction = way.tags:Find("junction") + local route = way.tags:Find("route") + local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) + local barrier = way.tags:Find("barrier") + local oneway = way.tags:Find("oneway") + local cycleway = way.tags:Find("cycleway") + local duration = way.tags:Find("duration") + local service = way.tags:Find("service") + local area = way.tags:Find("area") + local access = Access.find_access_tag(way, access_tags_hierachy) + + -- Second, parse the way according to these properties + + if ignore_areas and ("yes" == area) then + return 0 + end + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] then + return 0 + end + + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name +-- else +-- way.name = highway -- if no name exists, use way type + end + + if "roundabout" == junction then + way.roundabout = true; + end + + -- Handling ferries and piers + if (speed_profile[route] ~= nil and speed_profile[route] > 0) then + if durationIsValid(duration) then + way.duration = math.max( parseDuration(duration), 1 ); + end + way.direction = Way.bidirectional + if speed_profile[route] ~= nil then + highway = route; + end + if tonumber(way.duration) < 0 then + way.speed = speed_profile[highway] + end + end + + -- Set the avg speed on the way if it is accessible by road class + if (speed_profile[highway] ~= nil and way.speed == -1 ) then + if maxspeed > speed_profile[highway] then + way.speed = maxspeed + else + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile[highway], maxspeed) + end + end + + -- Set the avg speed on ways that are marked accessible + if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile["default"], maxspeed) + end + + -- Set access restriction flag if access is allowed under certain restrictions only + if access ~= "" and access_tag_restricted[access] then + way.is_access_restricted = true + end + + -- Set access restriction flag if service is allowed under certain restrictions only + if service ~= "" and service_tag_restricted[service] then + way.is_access_restricted = true + end + + -- Set direction according to tags on way + if obey_oneway then + if oneway == "no" or oneway == "0" or oneway == "false" then + way.direction = Way.bidirectional + elseif oneway == "-1" then + way.direction = Way.opposite + elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then + way.direction = Way.oneway + else + way.direction = Way.bidirectional + end + else + way.direction = Way.bidirectional + end + + -- Override speed settings if explicit forward/backward maxspeeds are given + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + if Way.bidirectional == way.direction then + way.backward_speed = way.speed + end + way.speed = maxspeed_forward + end + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + way.backward_speed = maxspeed_backward + end + + -- Override general direction settings of there is a specific one for our mode of travel + + if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then + way.ignore_in_grid = true + end + way.type = 1 + return 1 +end + +-- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT + +function node_vector_function(vector) + for v in vector.nodes do + node_function(v) + end +end diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index f6609d097..0fba9e730 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -109,12 +109,7 @@ function node_function (node) return 1 end -function way_function (way, numberOfNodesInWay) - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - +function way_function (way) -- initial routability check, filters out buildings, boundaries, etc local highway = way.tags:Find("highway") local route = way.tags:Find("route") diff --git a/profiles/car.lua b/profiles/car.lua index 095806590..33a7247d6 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -89,13 +89,7 @@ function node_function (node) end -function way_function (way, numberOfNodesInWay) - - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - +function way_function (way) -- First, get the properties of each way that we come across local highway = way.tags:Find("highway") local name = way.tags:Find("name") diff --git a/profiles/foot.lua b/profiles/foot.lua index fb0dee8db..6a15fb2ea 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -75,13 +75,8 @@ function node_function (node) return 1 end -function way_function (way, numberOfNodesInWay) +function way_function (way) - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - -- First, get the properties of each way that we come across local highway = way.tags:Find("highway") local name = way.tags:Find("name") diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 6379cdb70..f934fead5 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -46,12 +46,7 @@ function node_function (node) return 1 end -function way_function (way, numberOfNodesInWay) - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - +function way_function (way) local highway = way.tags:Find("highway") local name = way.tags:Find("name") local oneway = way.tags:Find("oneway") From f9abfbf68a1affbffbf3ee29a5109e93d1184eab Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 23 Feb 2013 08:33:33 +0100 Subject: [PATCH 159/161] compute turn penalties in lua profiles --- Contractor/EdgeBasedGraphFactory.cpp | 28 +++++++++++++++++------ Contractor/EdgeBasedGraphFactory.h | 16 ++++++++++--- createHierarchy.cpp | 7 ++++-- features/bicycle/ferry.feature | 6 ++--- features/bicycle/turn_penalty.feature | 33 +++++++++++++++++++++++++++ profiles/bicycle.lua | 12 ++++++++++ profiles/turnbot.lua | 8 +++++++ 7 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 features/bicycle/turn_penalty.feature create mode 100644 profiles/turnbot.lua diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 13a570e46..c4e3f3be4 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -150,7 +150,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( edgeBasedNodes.push_back(currentNode); } -void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { +void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State *myLuaState) { Percent p(_nodeBasedGraph->GetNumberOfNodes()); int numberOfSkippedTurns(0); int nodeBasedEdgeCounter(0); @@ -273,15 +273,16 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { if(_trafficLights.find(v) != _trafficLights.end()) { distance += speedProfile.trafficSignalPenalty; } - TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); - if(TurnInstructions.UTurn == turnInstruction) { + unsigned penalty = 0; + TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState); + if(turnInstruction == TurnInstructions.UTurn) distance += speedProfile.uTurnPenalty; - } // if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) { // distance += TurnInstructions.AccessRestrictionPenalty; // turnInstruction |= TurnInstructions.AccessRestrictionFlag; // } - + distance += penalty; + //distance += heightPenalty; //distance += ComputeTurnPenalty(u, v, w); @@ -325,7 +326,21 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); } -TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const { +TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const { + double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); + + if( speedProfile.has_turn_function ) { + try { + //call lua profile to compute turn penalty + penalty = luabind::call_function( myLuaState, "turn_function", 180-angle ); + } catch (const luabind::error &er) { + std::cerr << er.what() << std::endl; + //TODO handle lua errors + } + } else { + penalty = 0; + } + if(u == w) { return TurnInstructions.UTurn; } @@ -371,7 +386,6 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID return TurnInstructions.NoTurn; } - double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); return TurnInstructions.GetTurnDirectionOfInstruction(angle); } diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 1198ae971..76390fbc5 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -50,6 +50,14 @@ #include "../DataStructures/TurnInstructions.h" #include "../Util/BaseConfiguration.h" +extern "C" { +#include +#include +#include +} +#include + + class EdgeBasedGraphFactory : boost::noncopyable { public: struct EdgeBasedNode { @@ -71,9 +79,10 @@ public: }; struct SpeedProfileProperties{ - SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {} + SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_function(false) {} int trafficSignalPenalty; int uTurnPenalty; + bool has_turn_function; } speedProfile; private: @@ -133,10 +142,11 @@ public: template< class InputEdgeT > explicit EdgeBasedGraphFactory(int nodes, std::vector & inputEdges, std::vector & _bollardNodes, std::vector & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector & nI, SpeedProfileProperties speedProfile); - void Run(const char * originalEdgeDataFilename); + void Run(const char * originalEdgeDataFilename, lua_State *myLuaState); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes); - TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const; + void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData); + TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const; unsigned GetNumberOfNodes() const; }; diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 806164132..04ade55f4 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -133,7 +133,10 @@ int main (int argc, char *argv[]) { ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); } speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); - + + speedProfile.has_turn_function = lua_function_exists( myLuaState, "turn_function" ); + + std::vector edgeList; NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); in.close(); INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights"); @@ -148,7 +151,7 @@ int main (int argc, char *argv[]) { INFO("Generating edge-expanded graph representation"); EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); std::vector().swap(edgeList); - edgeBasedGraphFactory->Run(edgeOut.c_str()); + edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState); std::vector<_Restriction>().swap(inputRestrictions); std::vector().swap(bollardNodes); std::vector().swap(trafficLightNodes); diff --git a/features/bicycle/ferry.feature b/features/bicycle/ferry.feature index 87d9773c9..5d67df7ea 100644 --- a/features/bicycle/ferry.feature +++ b/features/bicycle/ferry.feature @@ -58,6 +58,6 @@ Feature: Bike - Handle ferry routes | abcd | | ferry | yes | 1:00 | When I route I should get - | from | to | route | time | - | a | d | abcd | 3600s +-1 | - | d | a | abcd | 3600s +-1 | \ No newline at end of file + | from | to | route | time | + | a | d | abcd | 3600s +-10 | + | d | a | abcd | 3600s +-10 | diff --git a/features/bicycle/turn_penalty.feature b/features/bicycle/turn_penalty.feature new file mode 100644 index 000000000..157cbf2d6 --- /dev/null +++ b/features/bicycle/turn_penalty.feature @@ -0,0 +1,33 @@ +@routing @bicycle @turn_penalty +Feature: Turn Penalties + + Background: + Given the profile "turnbot" + + Scenario: Bike - turns should incur a delay that depend on the angle + + Given the node map + | c | d | e | + | b | j | f | + | a | s | g | + + And the ways + | nodes | + | sj | + | ja | + | jb | + | jc | + | jd | + | je | + | jf | + | jg | + + When I route I should get + | from | to | route | time | distance | + | s | a | sj,ja | 39s +-1 | 242m +-1 | + | s | b | sj,jb | 30s +-1 | 200m +-1 | + | s | c | sj,jc | 29s +-1 | 242m +-1 | + | s | d | sj,jd | 20s +-1 | 200m +-1 | + | s | e | sj,je | 29s +-1 | 242m +-1 | + | s | f | sj,jf | 30s +-1 | 200m +-1 | + | s | g | sj,jg | 39s +-1 | 242m +-1 | \ No newline at end of file diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 0fba9e730..96c06b555 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -73,6 +73,8 @@ ignore_areas = true -- future feature traffic_signal_penalty = 5 u_turn_penalty = 20 use_turn_restrictions = false +turn_penalty = 60 +turn_bias = 1.4 -- End of globals function get_exceptions(vector) @@ -308,3 +310,13 @@ function way_function (way) way.type = 1 return 1 end + +function turn_function (angle) + -- compute turn penalty as angle^2, with a left/right bias + k = turn_penalty/(90.0*90.0) + if angle>=0 then + return angle*angle*k/turn_bias + else + return angle*angle*k*turn_bias + end +end diff --git a/profiles/turnbot.lua b/profiles/turnbot.lua new file mode 100644 index 000000000..1a96966f1 --- /dev/null +++ b/profiles/turnbot.lua @@ -0,0 +1,8 @@ +-- Testbot, with turn penalty +-- Used for testing turn penalties + +require 'testbot' + +function turn_function (angle) + return 200*math.abs(angle)/180 -- penalty +end From bec4e4437d57f340b44526f9ca0e9dc64c9086d2 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 27 Feb 2013 19:47:04 +0100 Subject: [PATCH 160/161] Minor code refactoring --- Contractor/EdgeBasedGraphFactory.cpp | 13 +++++++------ Contractor/EdgeBasedGraphFactory.h | 4 ++-- createHierarchy.cpp | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index c4e3f3be4..47d3f4f66 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -327,9 +327,9 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State } TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const { - double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); + const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); - if( speedProfile.has_turn_function ) { + if( speedProfile.has_turn_penalty_function ) { try { //call lua profile to compute turn penalty penalty = luabind::call_function( myLuaState, "turn_function", 180-angle ); @@ -364,18 +364,19 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) { //No turn possible. return TurnInstructions.NoTurn; - } else { - return TurnInstructions.StayOnRoundAbout; } + return TurnInstructions.StayOnRoundAbout; } //Does turn start or end on roundabout? if(data1.roundabout || data2.roundabout) { //We are entering the roundabout - if( (!data1.roundabout) && data2.roundabout) + if( (!data1.roundabout) && data2.roundabout) { return TurnInstructions.EnterRoundAbout; + } //We are leaving the roundabout - else if(data1.roundabout && (!data2.roundabout) ) + if(data1.roundabout && (!data2.roundabout) ) { return TurnInstructions.LeaveRoundAbout; + } } //If street names stay the same and if we are certain that it is not a roundabout, we skip it. diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 76390fbc5..f5d2f6607 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -79,10 +79,10 @@ public: }; struct SpeedProfileProperties{ - SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_function(false) {} + SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false) {} int trafficSignalPenalty; int uTurnPenalty; - bool has_turn_function; + bool has_turn_penalty_function; } speedProfile; private: diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 04ade55f4..7156cef32 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -134,7 +134,7 @@ int main (int argc, char *argv[]) { } speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); - speedProfile.has_turn_function = lua_function_exists( myLuaState, "turn_function" ); + speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" ); std::vector edgeList; NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); From 2cc2c967d19e5f85defc85b2a12b6eab47fc8c0c Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Thu, 28 Feb 2013 13:34:48 +0100 Subject: [PATCH 161/161] Compute turn angles in mercartor projection. Implements issues #596, #532 --- Contractor/EdgeBasedGraphFactory.cpp | 10 +++++----- Contractor/EdgeBasedGraphFactory.h | 1 + features/testbot/turns.feature | 15 +++++++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 47d3f4f66..fce247d31 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -397,12 +397,12 @@ unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { /* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/ template double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const { - const int v1x = A.lon - C.lon; - const int v1y = A.lat - C.lat; - const int v2x = B.lon - C.lon; - const int v2y = B.lat - C.lat; + const double v1x = (A.lon - C.lon)/100000.; + const double v1y = lat2y(A.lat/100000.) - lat2y(C.lat/100000.); + const double v2x = (B.lon - C.lon)/100000.; + const double v2y = lat2y(B.lat/100000.) - lat2y(C.lat/100000.); - double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI; + double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI; while(angle < 0) angle += 360; return angle; diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index f5d2f6607..e751a7169 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -45,6 +45,7 @@ #include "../Extractor/ExtractorStructs.h" #include "../DataStructures/HashTable.h" #include "../DataStructures/ImportEdge.h" +#include "../DataStructures/MercatorUtil.h" #include "../DataStructures/QueryEdge.h" #include "../DataStructures/Percent.h" #include "../DataStructures/TurnInstructions.h" diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature index f63a944d1..5a14c9e7b 100644 --- a/features/testbot/turns.feature +++ b/features/testbot/turns.feature @@ -97,20 +97,27 @@ Feature: Turn directions/codes | g | c | xg,xc | head,right,destination | | g | e | xg,xe | head,sharp_right,destination | - @todo - Scenario: Skadestuevej, København + Scenario: Turn instructions at high latitude https://github.com/DennisOSRM/Project-OSRM/issues/532 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 | + | 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 |