osrm-backend/features/support/data.rb
2012-12-10 17:05:22 +01:00

232 lines
6.5 KiB
Ruby

require 'OSM/objects' #osmlib gem
require 'OSM/Database'
require 'builder'
OSM_USER = 'osrm'
OSM_GENERATOR = 'osrm-test'
OSM_UID = 1
TEST_FOLDER = 'test'
DATA_FOLDER = 'cache'
PREPROCESS_LOG_FILE = 'preprocessing.log'
LOG_FILE = 'fail.log'
OSM_TIMESTAMP = '2000-00-00T00:00:00Z'
DEFAULT_SPEEDPROFILE = 'bicycle'
WAY_SPACING = 100
DEFAULT_GRID_SIZE = 100 #meters
ORIGIN = [1,1]
def sanitized_scenario_title
@sanitized_scenario_title ||= @scenario_title.gsub /[^0-9A-Za-z.\-]/, '_'
end
def set_grid_size meters
#the constant is calculated (with BigDecimal as: 1.0/(DEG_TO_RAD*EARTH_RADIUS_IN_METERS
#see ApproximateDistance() in ExtractorStructs.h
#it's only accurate when measuring along the equator, or going exactly north-south
@zoom = meters.to_f*0.8990679362704610899694577444566908445396483347536032203503E-5
end
def build_ways_from_table table
#add one unconnected way for each row
table.hashes.each_with_index do |row,ri|
#NOTE:
#currently osrm crashes when processing an isolated oneway with just 2 nodes, so we use 4
#this is relatated to the fact that a oneway deadend doesn't make a lot of sense
#if we stack ways on different x coordinates, outability tests get messed up, because osrm might pick a neighboring way if the one test can't be used.
#instead we place all lines as a string on the same y coordinate. this prevents using neightboring ways.
#a few nodes...
node1 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(0+WAY_SPACING*ri)*@zoom, ORIGIN[1]
node2 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(1+WAY_SPACING*ri)*@zoom, ORIGIN[1]
node3 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(2+WAY_SPACING*ri)*@zoom, ORIGIN[1]
node4 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(3+WAY_SPACING*ri)*@zoom, ORIGIN[1]
node5 = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+(4+WAY_SPACING*ri)*@zoom, ORIGIN[1]
node1.uid = OSM_UID
node2.uid = OSM_UID
node3.uid = OSM_UID
node4.uid = OSM_UID
node5.uid = OSM_UID
node1 << { :name => "a#{ri}" }
node2 << { :name => "b#{ri}" }
node3 << { :name => "c#{ri}" }
node4 << { :name => "d#{ri}" }
node5 << { :name => "e#{ri}" }
osm_db << node1
osm_db << node2
osm_db << node3
osm_db << node4
osm_db << node5
#...with a way between them
way = OSM::Way.new make_osm_id, OSM_USER, OSM_TIMESTAMP
way.uid = OSM_UID
way << node1
way << node2
way << node3
way << node4
way << node5
tags = row.dup
tags.delete 'forw'
tags.delete 'backw'
tags.reject! { |k,v| v=='' }
# sort tag keys in the form of 'node/....'
way_tags = { 'highway' => 'primary' }
node_tags = {}
tags.each_pair do |k,v|
if k =~ /node\/(.*)/
if v=='(nil)'
node_tags.delete k
else
node_tags[$1] = v
end
else
if v=='(nil)'
way_tags.delete k
else
way_tags[k] = v
end
end
end
way_tags['name'] = "w#{ri}"
way << way_tags
node3 << node_tags
osm_db << way
end
end
def find_node_by_name s
name_node_hash[s.to_s]
end
def find_way_by_name s
name_way_hash[s.to_s] || name_way_hash[s.to_s.reverse]
end
def reset_data
Dir.chdir TEST_FOLDER do
#clear_log
#clear_data_files
end
reset_speedprofile
reset_osm
@fingerprint = nil
end
def make_osm_id
@osm_id = @osm_id+1
end
def reset_osm
osm_db.clear
name_node_hash.clear
name_way_hash.clear
@osm_str = nil
@osm_hash = nil
##ID -1 causes trouble, so add a few nodes to avoid it
#node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, 0,0
#node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, 0,0
@osm_id = 0
end
def clear_data_files
File.delete *Dir.glob("#{DATA_FOLDER}/test.*")
end
def clear_log
File.delete *Dir.glob("*.log")
end
def osm_db
@osm_db ||= OSM::Database.new
end
def name_node_hash
@name_node_hash ||= {}
end
def name_way_hash
@name_way_hash ||= {}
end
def osm_str
return @osm_str if @osm_str
@osm_str = ''
doc = Builder::XmlMarkup.new :indent => 2, :target => @osm_str
doc.instruct!
osm_db.to_xml doc, OSM_GENERATOR
@osm_str
end
def write_osm
#write .oms file if needed
Dir.mkdir DATA_FOLDER unless File.exist? DATA_FOLDER
@osm_file = "#{DATA_FOLDER}/#{sanitized_scenario_title}_#{fingerprint}"
unless File.exist?("#{@osm_file}.osm")
File.open( "#{@osm_file}.osm", 'w') {|f| f.write(osm_str) }
end
end
def convert_osm_to_pbf
unless File.exist?("#{@osm_file}.osm.pbf")
log_preprocess_info
log "== Converting #{@osm_file}.osm to protobuffer format...", :preprocess
#redirect stdout and stderr to a log file avoid output in the cucumber console
unless system "osmosis --read-xml #{@osm_file}.osm --write-pbf #{@osm_file}.osm.pbf omitmetadata=true 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE}"
raise "Failed to convert to proto buffer format. Please see #{hash}.log for more info."
end
log '', :preprocess
end
end
def extracted?
File.exist?("#{@osm_file}.osrm") &&
File.exist?("#{@osm_file}.osrm.names") &&
File.exist?("#{@osm_file}.osrm.restrictions")
end
def prepared?
File.exist?("#{@osm_file}.osrm.hsgr")
end
def write_timestamp
File.open( "#{@osm_file}.osrm.timestamp", 'w') {|f| f.write(OSM_TIMESTAMP) }
end
def reprocess
Dir.chdir TEST_FOLDER do
write_osm
write_timestamp
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} ../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
log '', :preprocess
end
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/#{@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
log '', :preprocess
end
log_preprocess_done
write_server_ini
end
end