Class: GPSSpeed::Runner
- Inherits:
-
Object
- Object
- GPSSpeed::Runner
- Defined in:
- lib/gpsspeed/runner.rb
Constant Summary collapse
- DEFAULT_LENGTH =
500
- DEFAULT_SPEED_FMT =
'm/s'
- DEFAULT_LENGTH_FMT =
'm'
- LengthUnits =
{ 'm' => 1.0, 'ft' => 3.2808399, 'km' => 0.001, 'miles' => 0.000621371192, 'nm' => 0.000539956803 }
- SpeedUnits =
{ 'm/s' => 1.0, 'knots' => 1.9438612860586, 'km/h' => 3.6, 'mph' => 2.23693629 }
Instance Method Summary collapse
- #filter_distance_speeds ⇒ Object
-
#initialize(argv) ⇒ Runner
constructor
A new instance of Runner.
- #intersects_previous(candidate) ⇒ Object
- #length_conv(length) ⇒ Object
- #length_printf_fmt(width) ⇒ Object
- #list_distance_speeds ⇒ Object
- #parse_length(l) ⇒ Object
- #parse_options(argv) ⇒ Object
- #print_results ⇒ Object
- #read_gpx(filename) ⇒ Object
- #speed_conv(speed) ⇒ Object
Constructor Details
#initialize(argv) ⇒ Runner
Returns a new instance of Runner.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/gpsspeed/runner.rb', line 33 def initialize(argv) # Command line options @opt = {} argv @opt[:length] ||= DEFAULT_LENGTH # Minimum required distance @opt[:speed_fmt] ||= DEFAULT_SPEED_FMT @opt[:length_fmt] ||= DEFAULT_LENGTH_FMT filename, = argv read_gpx filename list_distance_speeds filter_distance_speeds print_results end |
Instance Method Details
#filter_distance_speeds ⇒ Object
121 122 123 124 125 126 |
# File 'lib/gpsspeed/runner.rb', line 121 def filter_distance_speeds @dist_speed_list.sort! {|a, b| a.speed_ms <=> b.speed_ms }.reverse! @dist_speed_list.reject! do |candidate| intersects_previous candidate end end |
#intersects_previous(candidate) ⇒ Object
128 129 130 131 132 133 134 135 136 |
# File 'lib/gpsspeed/runner.rb', line 128 def intersects_previous candidate intersects = nil @dist_speed_list[0...@dist_speed_list.index(candidate)].each do |prev| used = prev.begin..prev.end intersects ||= ((prev.begin..prev.end).to_a & (candidate.begin..candidate.end).to_a).any? break if intersects end intersects end |
#length_conv(length) ⇒ Object
151 152 153 |
# File 'lib/gpsspeed/runner.rb', line 151 def length_conv(length) length * LengthUnits[@opt[:length_fmt]] end |
#length_printf_fmt(width) ⇒ Object
155 156 157 |
# File 'lib/gpsspeed/runner.rb', line 155 def length_printf_fmt(width) "%#{width}.#{-Math::log10(LengthUnits[@opt[:length_fmt]]).to_i + 1}f" end |
#list_distance_speeds ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/gpsspeed/runner.rb', line 103 def list_distance_speeds @dist_speed_list = [] (0..(@points.size - 2)).each do |i| ((i + 1)..(@points.size - 1)).each do |j| dist = @points[i].utm.distance_to @points[j].utm next if dist < @opt[:length] ds = OpenStruct.new ds.distance = dist ds.begin = i ds.end = j ds.dt = (@points[j].date_time - @points[i].date_time) * 24.0 * 60.0 * 60.0 ds.speed_ms = dist / ds.dt @dist_speed_list << ds break end end end |
#parse_length(l) ⇒ Object
49 50 51 52 53 54 55 56 57 |
# File 'lib/gpsspeed/runner.rb', line 49 def parse_length(l) LengthUnits.each do |name, factor| m = l.match /^(\d+(.\d+)?)\s?#{name}$/i return m[1].to_f * factor if m end m = l.match /^(\d+(.\d+)?)$/i throw RuntimeError.new('Illegal length format: ' + l) unless m m[1].to_f end |
#parse_options(argv) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/gpsspeed/runner.rb', line 59 def (argv) OptionParser.new do |op| op. = "Usage: gpsspeed [options] <input.gpx>" op.on("-l", "--length DIST", "Minimum required length (default #{DEFAULT_LENGTH}m)", " Accepts #{LengthUnits.keys.join ','}") do |l| @opt[:length] = parse_length l end op.on("-s", "--speed-format FMT", "Select speed format (default #{DEFAULT_SPEED_FMT})", " Accepts #{SpeedUnits.keys.join ','}") do |fmt| @opt[:speed_fmt] = fmt end op.on("-f", "--length-format FMT", "Select length format (default #{DEFAULT_LENGTH_FMT})", " Accepts #{LengthUnits.keys.join ','}") do |fmt| @opt[:length_fmt] = fmt end op.on_tail("-h", "--help", "Show this message") do puts op exit end end.parse! argv end |
#print_results ⇒ Object
138 139 140 141 142 143 144 145 |
# File 'lib/gpsspeed/runner.rb', line 138 def print_results puts '%20s%10s%10s%10s%20s%20s' % ["Speed [#{@opt[:speed_fmt]}]", '#frm', '#to', '#n', 'time [s]', "Distance [#{@opt[:length_fmt]}]"] (@dist_speed_list[0..39] || []).each do |ds| puts "%20.4f%10i%10i%10i%20.2f#{length_printf_fmt(20)}" % [speed_conv(ds.speed_ms), ds.begin, ds.end, ds.end - ds.begin + 1, ds.dt, length_conv(ds.distance)] end end |
#read_gpx(filename) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/gpsspeed/runner.rb', line 81 def read_gpx filename throw RuntimeError.new("Please specify file name") unless filename doc = nil File.open filename do |f| doc = REXML::Document.new f end @points = [] REXML::XPath.each doc, '//trkpt' do |trkpt| lat = trkpt.attributes['lat'] lon = trkpt.attributes['lon'] date_time = DateTime.strptime trkpt.get_elements('time').first.text pp = OpenStruct.new pp.latlon = GeoUtm::LatLon.new lat.to_f, lon.to_f pp.utm = pp.latlon.to_utm GeoUtm::Ellipsoid::lookup(:wgs84), @points.first && @points.first.utm.zone pp.date_time = date_time @points << pp end @points.sort! {|a, b| a.date_time <=> b.date_time } # puts "Read #{@points.size} track points" end |
#speed_conv(speed) ⇒ Object
147 148 149 |
# File 'lib/gpsspeed/runner.rb', line 147 def speed_conv(speed) speed * SpeedUnits[@opt[:speed_fmt]] end |