From 3ec4a049c5536bc6beed1419ef78452aa1628a54 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 11 Oct 2012 14:34:18 +0200 Subject: [PATCH 01/11] update rakefile to work with lua profiles --- Rakefile | 59 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/Rakefile b/Rakefile index 2e7a44d61..b16955198 100644 --- a/Rakefile +++ b/Rakefile @@ -4,8 +4,8 @@ require 'digest/sha1' require 'cucumber/rake/task' require 'sys/proctable' -SANDBOX = 'sandbox' -DATA_FOLDER = 'osm_data' +DATA_FOLDER = 'sandbox' +PROFILE = 'bicycle' Cucumber::Rake::Task.new do |t| t.cucumber_opts = %w{--format pretty} @@ -62,12 +62,12 @@ def write_server_ini osm_file IP = 0.0.0.0 Port = 5000 - hsgrData=#{DATA_FOLDER}/#{osm_file}.osrm.hsgr - nodesData=#{DATA_FOLDER}/#{osm_file}.osrm.nodes - edgesData=#{DATA_FOLDER}/#{osm_file}.osrm.edges - ramIndex=#{DATA_FOLDER}/#{osm_file}.osrm.ramIndex - fileIndex=#{DATA_FOLDER}/#{osm_file}.osrm.fileIndex - namesData=#{DATA_FOLDER}/#{osm_file}.osrm.names + hsgrData=#{osm_file}.osrm.hsgr + nodesData=#{osm_file}.osrm.nodes + edgesData=#{osm_file}.osrm.edges + ramIndex=#{osm_file}.osrm.ramIndex + fileIndex=#{osm_file}.osrm.fileIndex + namesData=#{osm_file}.osrm.names EOF File.open( 'server.ini', 'w') {|f| f.write( s ) } end @@ -83,46 +83,48 @@ end desc "Setup config files." task :setup do - Dir.mkdir "#{SANDBOX}/#{DATA_FOLDER}" unless File.exist? "#{SANDBOX}/#{DATA_FOLDER}" - ['server.ini','speedprofile.ini','extractor.ini','contractor.ini'].each do |file| - unless File.exist? "#{SANDBOX}/#{file}" - puts "Copying #{file} template to sandbox/#{file}" - FileUtils.cp file, "#{SANDBOX}/#{file}" + Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}" + ['server.ini','extractor.ini','contractor.ini'].each do |file| + unless File.exist? "#{DATA_FOLDER}/#{file}" + puts "Copying #{file} template to #{DATA_FOLDER}/#{file}" + FileUtils.cp file, "#{DATA_FOLDER}/#{file}" end end end desc "Download OSM data." task :download => :setup do + Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}" puts "Downloading..." - raise "Error while downloading data." unless system "curl http://download.geofabrik.de/osm/europe/#{osm_data_country}.osm.pbf -o #{SANDBOX}/#{DATA_FOLDER}/#{osm_data_country}.osm.pbf" + puts "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf" + raise "Error while downloading data." unless system "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf" if osm_data_area_bbox puts "Cropping and converting to protobuffer..." - raise "Error while cropping data." unless system "osmosis --read-pbf file=#{SANDBOX}/#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{SANDBOX}/#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true" + raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true" end end desc "Crop OSM data" task :crop do if osm_data_area_bbox - raise "Error while cropping data." unless system "osmosis --read-pbf file=#{SANDBOX}/#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{SANDBOX}/#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true" + raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true" end end desc "Reprocess OSM data." task :process => :setup do - Dir.chdir SANDBOX do - raise "Error while extracting data." unless system "../osrm-extract #{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf" + Dir.chdir DATA_FOLDER do + raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua" puts - raise "Error while preparing data." unless system "../osrm-prepare #{DATA_FOLDER}/#{osm_data_area_name}.osrm #{DATA_FOLDER}/#{osm_data_area_name}.osrm.restrictions" + raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua" puts end end desc "Delete preprocessing files." task :clean do - File.delete *Dir.glob("#{SANDBOX}/#{DATA_FOLDER}/*.osrm") - File.delete *Dir.glob("#{SANDBOX}/#{DATA_FOLDER}/*.osrm.*") + File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm") + File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*") end desc "Run all cucumber test" @@ -133,7 +135,7 @@ end desc "Run the routing server in the terminal. Press Ctrl-C to stop." task :run => :setup do - Dir.chdir SANDBOX do + Dir.chdir DATA_FOLDER do write_server_ini osm_data_area_name system "../osrm-routed" end @@ -141,7 +143,7 @@ end desc "Launch the routing server in the background. Use rake:down to stop it." task :up => :setup do - Dir.chdir SANDBOX do + Dir.chdir DATA_FOLDER do abort("Already up.") if up? write_server_ini osm_data_area_name pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log') @@ -160,8 +162,11 @@ end desc "Stop the routing server." task :down do pid = find_pid 'osrm-routed' - abort("Already down.") unless pid - Process.kill 'TERM', pid + if pid + Process.kill 'TERM', pid + else + puts "Already down." + end end desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes." @@ -180,3 +185,7 @@ task :pid do puts "#{pid}\t#{state}" end end + +desc "Stop, reprocess and restart." +task :update => [:down,:process,:up] do +end From f40550b18c5f750a2ef40b003193adf0141e5841 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 11 Oct 2012 16:50:17 +0200 Subject: [PATCH 02/11] bike speeds on pedestrian areas --- profiles/bicycle.lua | 85 ++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index e75944093..b082dc747 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -6,9 +6,10 @@ 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 } -ignore_in_grid = { ["ferry"] = true } -speed_profile = { +default_speed = 16 + +main_speeds = { ["cycleway"] = 18, ["primary"] = 17, ["primary_link"] = 17, @@ -23,18 +24,30 @@ speed_profile = { ["service"] = 16, ["track"] = 13, ["path"] = 13, + ["footway"] = 12, + ["pedestrian"] = 12, + ["pier"] = 12, + ["steps"] = 2 +} + +pedestrian_speeds = { ["footway"] = 5, ["pedestrian"] = 5, ["pier"] = 5, - ["steps"] = 1, - ["default"] = 18, - ["ferry"] = 5, - ["train"] = 80, - ["railway"] = 60, - ["subway"] = 50, - ["light_rail"] = 40, - ["monorail"] = 40, - ["tram"] = 40 + ["steps"] = 2, +} + +railway_speeds = { + ["train"] = 10, + ["railway"] = 10, + ["subway"] = 10, + ["light_rail"] = 10, + ["monorail"] = 10, + ["tram"] = 10 +} + +route_speeds = { + ["ferry"] = 5 } take_minimum_of_speeds = true @@ -131,33 +144,37 @@ function way_function (way, numberOfNodesInWay) way.name = highway -- if no name exists, use way type end - if (speed_profile[route] and speed_profile[route] > 0) or (speed_profile[man_made] and speed_profile[man_made] > 0) then - -- ferries and piers + if route_speeds[route] then + -- ferries + way.direction = Way.bidirectional + way.ignore_in_grid = true if durationIsValid(duration) then - way.speed = math.max( duration / math.max(1, numberOfNodesInWay-1) ) - way.is_duration_set = true; + way.speed = math.max( parseDuration(duration) / math.max(1, numberOfNodesInWay-1) ) + way.is_duration_set = true + else + way.speed = route_speeds[route] end - way.direction = Way.bidirectional; - if speed_profile[route] ~= nil then - highway = route; - elseif speed_profile[man_made] ~= nil then - highway = man_made; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - elseif railway and speed_profile[railway] then + elseif railway and railway_speeds[railway] then -- trains and subways if access and access_tag_whitelist[access] then - way.speed = speed_profile[railway] + 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 else - -- ways - if speed_profile[highway] then - way.speed = speed_profile[highway] - elseif access_tag_whitelist[access] then - way.speed = speed_profile["default"] + -- 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 @@ -212,11 +229,11 @@ function way_function (way, numberOfNodesInWay) -- cycleways if cycleway and cycleway_tags[cycleway] then - way.speed = speed_profile["cycleway"] + way.speed = main_speeds["cycleway"] elseif cycleway_left and cycleway_tags[cycleway_left] then - way.speed = speed_profile["cycleway"] + way.speed = main_speeds["cycleway"] elseif cycleway_right and cycleway_tags[cycleway_right] then - way.speed = speed_profile["cycleway"] + way.speed = main_speeds["cycleway"] end way.type = 1 From d9af615db90da83d4ea0b5a4d639b0075e0a1b4f Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 11 Oct 2012 19:13:58 +0200 Subject: [PATCH 03/11] remove incorrect @bicycle tag from car test --- features/car/destination.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/car/destination.feature b/features/car/destination.feature index ca4263956..35314369a 100644 --- a/features/car/destination.feature +++ b/features/car/destination.feature @@ -1,4 +1,4 @@ -@routing @bicycle @destination @todo +@routing @car @destination @todo Feature: Car - Destination only, no passing through Background: From 3a706cade7f06333198e685e87e46c580889c73c Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 13 Oct 2012 14:05:13 +0200 Subject: [PATCH 04/11] in tests, use profile arg instead of copying file --- features/support/config.rb | 4 ---- features/support/data.rb | 5 ++--- features/support/hash.rb | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/features/support/config.rb b/features/support/config.rb index a110488e3..c66cdde5f 100644 --- a/features/support/config.rb +++ b/features/support/config.rb @@ -11,10 +11,6 @@ def read_speedprofile profile @speedprofile = profile end -def write_speedprofile - FileUtils.copy_file "../profiles/#{@speedprofile}.lua", "profile.lua" -end - def write_server_ini s=<<-EOF Threads = 1 diff --git a/features/support/data.rb b/features/support/data.rb index 8b333d301..88f211be5 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -200,13 +200,12 @@ end def reprocess Dir.chdir TEST_FOLDER do - write_speedprofile write_osm convert_osm_to_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}" + unless system "../osrm-extract #{@osm_file}.osm.pbf 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@speedprofile}.lua" log "*** Exited with code #{$?.exitstatus}.", :preprocess raise OSRMError.new 'osrm-extract', $?.exitstatus, "*** osrm-extract exited with code #{$?.exitstatus}. The file preprocess.log might contain more info." end @@ -215,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}" + unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} ../profiles/#{@speedprofile}.lua" log "*** Exited with code #{$?.exitstatus}.", :preprocess raise OSRMError.new 'osrm-prepare', $?.exitstatus, "*** osrm-prepare exited with code #{$?.exitstatus}. The file preprocess.log might contain more info." end diff --git a/features/support/hash.rb b/features/support/hash.rb index c4c0bf944..2c729fe21 100644 --- a/features/support/hash.rb +++ b/features/support/hash.rb @@ -12,7 +12,7 @@ def hash_of_file path end def speedprofile_hash - @speedprofile_hash ||= hash_of_file "profile.lua" + @speedprofile_hash ||= hash_of_file "../profiles/#{@speedprofile}.lua" end def osm_hash From b5f2a98e89527a87e18f775a6ac25de414d31b2c Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Wed, 17 Oct 2012 09:50:00 +0200 Subject: [PATCH 05/11] make clang++ default compiler on Mac --- SConstruct | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SConstruct b/SConstruct index 866e12b90..754ea057a 100644 --- a/SConstruct +++ b/SConstruct @@ -72,6 +72,8 @@ conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf if GetOption('cxx') is None: #default Compiler + if sys.platform == 'darwin': #Mac OS X + env['CXX'] = 'clang++' print 'Using default C++ Compiler: ', env['CXX'].strip() else: env.Replace(CXX = GetOption('cxx')) From ad5b96d6f2d9d683ace2fec85cf6ba19d75f7441 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 18 Oct 2012 14:50:21 +0200 Subject: [PATCH 06/11] verify distance in traffic signal tests --- features/testbot/penalty.feature | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/testbot/penalty.feature b/features/testbot/penalty.feature index 4d956bcfe..f680eac4e 100644 --- a/features/testbot/penalty.feature +++ b/features/testbot/penalty.feature @@ -5,7 +5,7 @@ Testbot uses a signal penalty of 7s. Background: Given the speedprofile "testbot" - Scenario: Passing a traffic signal should incur a delay + Scenario: Traffic signals should incur a delay, without changing distance Given the node map | a | b | c | | d | e | f | @@ -20,9 +20,9 @@ Testbot uses a signal penalty of 7s. | def | When I route I should get - | from | to | route | time | - | a | c | abc | 20s +-1 | - | d | f | def | 27s +-1 | + | from | to | route | time | distance | + | a | c | abc | 20s +-1 | 200m +-1 | + | d | f | def | 27s +-1 | 200m +-1 | Scenario: Signal penalty should not depend on way type Given the node map From 57dc1e03b1b8ca91637d95c643db469593b17707 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sat, 13 Oct 2012 23:38:54 +0200 Subject: [PATCH 07/11] bikes, handle parking areas and train platforms --- features/bicycle/area.feature | 58 ++++++++++++++++++++++++++++++++-- features/bicycle/train.feature | 2 +- profiles/bicycle.lua | 25 +++++++++++++-- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/features/bicycle/area.feature b/features/bicycle/area.feature index ab954dd86..267e57539 100644 --- a/features/bicycle/area.feature +++ b/features/bicycle/area.feature @@ -3,7 +3,8 @@ Feature: Bike - Squares and other areas Background: Given the speedprofile "bicycle" - + + @square Scenario: Bike - Route along edge of a squares Given the node map | x | | @@ -25,7 +26,8 @@ Feature: Bike - Squares and other areas | d | c | abcda | | d | a | abcda | | a | d | abcda | - + + @building Scenario: Bike - Don't route on buildings Given the node map | x | | @@ -47,3 +49,55 @@ Feature: Bike - Squares and other areas | d | c | | | d | a | | | a | d | | + + @parking + Scenario: Bike - parking areas + Given the node map + | e | | | f | + | x | a | b | y | + | | d | c | | + + And the ways + | nodes | highway | amenity | + | xa | primary | | + | by | primary | | + | xefy | primary | | + | abcda | (nil) | parking | + + When I route I should get + | from | to | route | + | x | y | xa,abcda,by | + | y | x | by,abcda,xa | + | a | b | abcda | + | a | d | abcda | + | b | c | abcda | + | c | b | abcda | + | c | d | abcda | + | d | c | abcda | + | d | a | abcda | + | a | d | abcda | + + @train @platform + Scenario: Bike - railway platforms + Given the node map + | x | a | b | y | + | | d | c | | + + And the ways + | nodes | highway | railway | + | xa | primary | | + | by | primary | | + | abcda | (nil) | platform | + + When I route I should get + | from | to | route | + | x | y | xa,abcda,by | + | y | x | by,abcda,xa | + | a | b | abcda | + | a | d | abcda | + | b | c | abcda | + | c | b | abcda | + | c | d | abcda | + | d | c | abcda | + | d | a | abcda | + | a | d | abcda | diff --git a/features/bicycle/train.feature b/features/bicycle/train.feature index cb7a76171..dd67e08db 100644 --- a/features/bicycle/train.feature +++ b/features/bicycle/train.feature @@ -1,4 +1,4 @@ -@routing @bicycle @train @todo +@routing @bicycle @train Feature: Bike - Handle ferry routes Bringing bikes on trains and subways diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index b082dc747..8f24d791e 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -34,7 +34,7 @@ pedestrian_speeds = { ["footway"] = 5, ["pedestrian"] = 5, ["pier"] = 5, - ["steps"] = 2, + ["steps"] = 2 } railway_speeds = { @@ -46,6 +46,15 @@ railway_speeds = { ["tram"] = 10 } +platform_speeds = { + ["platform"] = 5 +} + +amenity_speeds = { + ["parking"] = 10, + ["parking_entrance"] = 10 +} + route_speeds = { ["ferry"] = 5 } @@ -123,10 +132,14 @@ 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 = find_access_tag(way) -- only route on things with highway tag set (not buildings, boundaries, etc) - if (not highway or highway == '') and (not route or route == '') and (not railway or railway=='') then + if (not highway or highway == '') and + (not route or route == '') and + (not railway or railway=='') and + (not amenity or amenity=='') then return 0 end @@ -154,8 +167,11 @@ function way_function (way, numberOfNodesInWay) else way.speed = route_speeds[route] end + elseif railway and platform_speeds[railway] then + -- railway platforms + way.speed = platform_speeds[railway] elseif railway and railway_speeds[railway] then - -- trains and subways + -- railways if access and access_tag_whitelist[access] then way.speed = railway_speeds[railway] way.direction = Way.bidirectional @@ -167,6 +183,9 @@ function way_function (way, numberOfNodesInWay) else way.speed = pedestrian_speeds[highway] -- pushing bikes end + elseif amenity and amenity_speeds[amenity] then + -- parking areas + way.speed = amenity_speeds[amenity] else -- regular ways if main_speeds[highway] then From d1d800025d950df387cf67a6bd10508accf49111 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Sat, 20 Oct 2012 21:11:37 +0200 Subject: [PATCH 08/11] changing gdal check to version free include dir --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 866e12b90..fa553546d 100644 --- a/SConstruct +++ b/SConstruct @@ -157,7 +157,7 @@ if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'): print "bz2 library not found. Exiting" Exit(-1) if GetOption('withtools') is not None: - if not conf.CheckLibWithHeader('gdal1.7.0', 'gdal/gdal.h', 'CXX'): + if not conf.CheckLibWithHeader('gdal', 'gdal/gdal.h', 'CXX'): print "gdal library not found. Exiting" Exit(-1) if not conf.CheckLibWithHeader('osmpbf', 'osmpbf/osmpbf.h', 'CXX'): From 9dd45cceabb66b59f9bbcfe226b5cbe3eba652ce Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 26 Oct 2012 13:11:38 +0200 Subject: [PATCH 09/11] fix invalid ref to numberOfSegments in foot profile --- profiles/foot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/foot.lua b/profiles/foot.lua index 959e774e4..efa4ed6a7 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -128,7 +128,7 @@ function way_function (way, numberOfNodesInWay) (speed_profile[man_made] ~= nil and speed_profile[man_made] > 0) then if durationIsValid(duration) then - way.speed = parseDuration / math.max(1, numberOfSegments-1); + way.speed = parseDuration / math.max(1, numberOfNodesInWay-1); way.is_duration_set = true; end way.direction = Way.bidirectional; From 48c6145bdfa0081c69fa1b5fc712b5f127379fa1 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 26 Oct 2012 18:20:37 +0200 Subject: [PATCH 10/11] Douglas Peucker now twice as fast by using integer arithmetic only --- Algorithms/DouglasPeucker.h | 81 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/Algorithms/DouglasPeucker.h b/Algorithms/DouglasPeucker.h index e0feb45d5..215d2a1ce 100644 --- a/Algorithms/DouglasPeucker.h +++ b/Algorithms/DouglasPeucker.h @@ -29,15 +29,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../DataStructures/Coordinate.h" /*This class object computes the bitvector of indicating generalized input points - * according to the (Ramer-)Douglas-Peucker algorithm. + * according to the (Ramer-)Douglas-Peucker algorithm. Runtime n\log n calls to fastDistance * * Input is vector of pairs. Each pair consists of the point information and a bit * indicating if the points is present in the generalization. * Note: points may also be pre-selected*/ //These thresholds are more or less heuristically chosen. -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 -static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. }; +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +static double DouglasPeuckerThresholds[19] = { 32000000, 16240000, 80240000, 40240000, 20000000, 10000000, 500000, 240000, 120000, 60000, 30000, 19000, 5000, 2000, 200, 16, 6, 3, 3 }; template class DouglasPeucker { @@ -45,58 +45,27 @@ private: typedef std::pair PairOfPoints; //Stack to simulate the recursion std::stack recursionStack; - - double ComputeDistanceOfPointToLine(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target) const { - double r = 0.; - const double x = static_cast(inputPoint.lat); - const double y = static_cast(inputPoint.lon); - const double a = static_cast(source.lat); - const double b = static_cast(source.lon); - const double c = static_cast(target.lat); - const double d = static_cast(target.lon); - double p,q,mX,nY; - if(fabs(a - c) <= FLT_EPSILON) { - const double m = (d-b)/(c-a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m*y)) + (m*m*a - m*b))/(1 + m*m); - q = b + m*(p - a); - } else { - p = c; - q = y; - } - nY = (d*p - c*q)/(a*d - b*c); - mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio - r = std::isnan(mX) ? 0. : mX; - if(r<=0.){ - return ((b - y)*(b - y) + (a - x)*(a - x)); - } - else if(r >= 1.){ - return ((d - y)*(d - y) + (c - x)*(c - x)); - - } - // point lies in between - return (p-x)*(p-x) + (q-y)*(q-y); - } - public: void Run(std::vector & inputVector, const unsigned zoomLevel) { + const unsigned sizeOfInputVector = inputVector.size(); { assert(zoomLevel < 19); assert(1 < inputVector.size()); std::size_t leftBorderOfRange = 0; std::size_t rightBorderOfRange = 1; + //Sweep linerarily over array and identify those ranges that need to be checked -// recursionStack.hint(inputVector.size()); + //decision points have been previously marked do { assert(inputVector[leftBorderOfRange].necessary); - assert(inputVector[inputVector.size()-1].necessary); + assert(inputVector[inputVector.back()].necessary); if(inputVector[rightBorderOfRange].necessary) { recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange)); leftBorderOfRange = rightBorderOfRange; } ++rightBorderOfRange; - } while( rightBorderOfRange < inputVector.size()); + } while( rightBorderOfRange < sizeOfInputVector); } while(!recursionStack.empty()) { //pop next element @@ -104,13 +73,13 @@ public: recursionStack.pop(); assert(inputVector[pair.first].necessary); assert(inputVector[pair.second].necessary); - assert(pair.second < inputVector.size()); + assert(pair.second < sizeOfInputVector); assert(pair.first < pair.second); - double maxDistance = -DBL_MAX; + int maxDistance = -INT_MIN; std::size_t indexOfFarthestElement = pair.second; //find index idx of element with maxDistance for(std::size_t i = pair.first+1; i < pair.second; ++i){ - const double distance = std::fabs(ComputeDistanceOfPointToLine(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location)); + const int distance = fastDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location); if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) { indexOfFarthestElement = i; maxDistance = distance; @@ -127,6 +96,34 @@ public: } } } + + /** + * This distance computation does integer arithmetic only and is about twice as fast as + * the other distance function. It is an approximation only, but works more or less ok. + */ + template + double fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) { + int p2x = (segB.lon - segA.lat); + int p2y = (segB.lon - segA.lat); + int something = p2x*p2x + p2y*p2y; + int u = ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something; + + if (u > 1) + u = 1; + else if (u < 0) + u = 0; + + int x = segA.lon + u * p2x; + int y = segA.lat + u * p2y; + + int dx = x - point.lon; + int dy = y - point.lat; + + int dist = (dx*dx + dy*dy); + + return dist; + } + }; #endif /* DOUGLASPEUCKER_H_ */ From 313466941bd3d9674d7f5c2ea78fc7d4fe0fb4da Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 26 Oct 2012 18:31:31 +0200 Subject: [PATCH 11/11] Making alternative route optional --- Plugins/ViaRoutePlugin.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 01f4afed1..738ad5639 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -127,28 +127,13 @@ public: segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1]; rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes); } - if(1 == rawRoute.segmentEndCoordinates.size()) { + if(( "false" != routeParameters.options.Find("alt") ) (&& (1 == rawRoute.segmentEndCoordinates.size())) { // INFO("Checking for alternative paths"); searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute); } else { searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute); } -// std::cout << "latitude,longitude" << std::endl; -// for(unsigned i = 0; i < rawRoute.computedShortestPath.size(); ++i) { -// _Coordinate current; -// searchEngine->GetCoordinatesForNodeID(rawRoute.computedShortestPath[i].node, current); -// std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl; -// } -// std::cout << std::endl; -// -// std::cout << "latitude,longitude" << std::endl; -// for(unsigned i = 0; i < rawRoute.computedAlternativePath.size(); ++i) { -// _Coordinate current; -// searchEngine->GetCoordinatesForNodeID(rawRoute.computedAlternativePath[i].node, current); -// std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl; -// } -// std::cout << std::endl; if(INT_MAX == rawRoute.lengthOfShortestPath ) {