Skip to content

Commit

Permalink
made unit tests work
Browse files Browse the repository at this point in the history
  • Loading branch information
kbb29 authored and andrewhao committed May 9, 2015
1 parent db243ef commit fbe8c68
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 148 deletions.
2 changes: 2 additions & 0 deletions bin/gpx_distance
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env ruby

require File.expand_path('../../lib/gpx', __FILE__)

filename = ARGV[0]
Expand Down
86 changes: 2 additions & 84 deletions bin/gpx_smooth
Original file line number Diff line number Diff line change
@@ -1,88 +1,8 @@
#!/usr/bin/env ruby

require File.expand_path('../../lib/gpx', __FILE__)
require 'optparse'

=begin
class GPX::TrackPoint < GPX::Point
attr_accessor :new_lat, :new_lon, :new_elevation

def update_new_values
self.lon = self.new_lon if self.new_lon
self.lat = self.new_lat if self.new_lat
self.elevation = self.new_elevation if self.new_elevation
end
=end


=begin
class GPX::Segment < GPX::Base
def find_point_by_time_or_offset(indicator)
if indicator.nil?
return nil
elsif indicator.is_a?(Integer)
return self.closest_point(self.earliest_point.time + indicator)
elsif(indicator.is_a?(Time))
return self.closest_point(indicator)
else
raise Exception, "find_end_point_by_time_or_offset requires an argument of type Time or Integer"
end
end

def smooth_location_by_average(opts={})
seconds_either_side = opts[:averaging_window] || 20
earliest = (find_point_by_time_or_offset(opts[:start]) || self.earliest_point).time
latest = (find_point_by_time_or_offset(opts[:end]) || self.latest_point).time
self.points.each do |point|
next if point.time > latest || point.time < earliest
lat_av = 0.to_f
lon_av = 0.to_f
alt_av = 0.to_f
n = 0
(-1*seconds_either_side..seconds_either_side).each do |k|
contributing_point = self.closest_point(point.time + k)
lat_av += contributing_point.lat
lon_av += contributing_point.lon
alt_av += contributing_point.elevation
n += 1
end
point.new_lon = (lon_av) / n
point.new_elevation = (alt_av) / n
point.new_lat = (lat_av) / n
end
last_pt = nil
@distance = 0
self.points.each do |point|
if point.time <= latest || point.time >= earliest
point.update_new_values
end
@distance += haversine_distance(last_pt, point) unless last_pt.nil?
last_pt = point
end
end

end
=end

=begin
class GPX::Track < GPX::Base
def recalculate_distance
@distance = 0
segments.each do |seg|
@distance += seg.distance
end
end
end

class GPX::GPXFile < GPX::Base
def recalculate_distance
@distance = 0
tracks.each do |track|
track.recalculate_distance
@distance += track.distance
end
end
end
=end


def str_to_int_or_time(str)
if str =~ /\A\d{10}\Z/
Expand Down Expand Up @@ -141,5 +61,3 @@ else
puts gpx.to_s(false)
end



2 changes: 2 additions & 0 deletions gpx.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ Gem::Specification.new do |s|
s.homepage = "http://www.github.com/andrewhao/gpx"
s.add_dependency 'rake'
s.add_dependency 'nokogiri'
s.add_development_dependency 'bundler'
s.add_development_dependency 'minitest'
end
1 change: 1 addition & 0 deletions lib/gpx/gpx_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def generate_xml_doc
xml.trkpt(lat: p.lat, lon: p.lon) {
xml.time p.time.xmlschema unless p.time.nil?
xml.ele p.elevation unless p.elevation.nil?
xml << p.extensions.to_xml unless p.extensions.nil?
}
end
}
Expand Down
4 changes: 3 additions & 1 deletion lib/gpx/point.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module GPX
# The base class for all points. Trackpoint and Waypoint both descend from this base class.
class Point < Base
D_TO_R = Math::PI/180.0;
attr_accessor :lat, :lon, :time, :elevation, :gpx_file, :speed
attr_accessor :lat, :lon, :time, :elevation, :gpx_file, :speed, :extensions

# When you need to manipulate individual points, you can create a Point
# object with a latitude, a longitude, an elevation, and a time. In
Expand All @@ -40,12 +40,14 @@ def initialize(opts = {:lat => 0.0, :lon => 0.0, :elevation => 0.0, :time => Tim
@time = (Time.xmlschema(elem.at("time").inner_text) rescue nil)
@elevation = elem.at("ele").inner_text.to_f unless elem.at("ele").nil?
@speed = elem.at("speed").inner_text.to_f unless elem.at("speed").nil?
@extensions = elem.at("extensions") unless elem.at("extensions").nil?
else
@lat = opts[:lat]
@lon = opts[:lon]
@elevation = opts[:elevation]
@time = opts[:time]
@speed = opts[:speed]
@extensions = opts[:extensions]
end

end
Expand Down
76 changes: 39 additions & 37 deletions lib/gpx/segment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,7 @@ def initialize(opts = {})
if segment_element.is_a?(Nokogiri::XML::Node)
segment_element.search("trkpt").each do |trkpt|
pt = TrackPoint.new(:element => trkpt, :segment => self, :gpx_file => @gpx_file)
unless pt.time.nil?
@earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
@latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)
end
unless pt.elevation.nil?
@lowest_point = pt if(@lowest_point.nil? or pt.elevation < @lowest_point.elevation)
@highest_point = pt if(@highest_point.nil? or pt.elevation > @highest_point.elevation)
end
@bounds.min_lat = pt.lat if pt.lat < @bounds.min_lat
@bounds.min_lon = pt.lon if pt.lon < @bounds.min_lon
@bounds.max_lat = pt.lat if pt.lat > @bounds.max_lat
@bounds.max_lon = pt.lon if pt.lon > @bounds.max_lon

@distance += haversine_distance(last_pt, pt) unless last_pt.nil?

@points << pt
last_pt = pt
append_point(pt)
end
end
end
Expand All @@ -73,10 +57,14 @@ def initialize(opts = {})
# Tack on a point to this Segment. All meta-data will be updated.
def append_point(pt)
last_pt = @points[-1]
@earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
@latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)
@lowest_point = pt if(@lowest_point.nil? or pt.elevation < @lowest_point.elevation)
@highest_point = pt if(@highest_point.nil? or pt.elevation > @highest_point.elevation)
unless pt.time.nil?
@earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
@latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)
end
unless pt.elevation.nil?
@lowest_point = pt if(@lowest_point.nil? or pt.elevation < @lowest_point.elevation)
@highest_point = pt if(@highest_point.nil? or pt.elevation > @highest_point.elevation)
end
@bounds.min_lat = pt.lat if pt.lat < @bounds.min_lat
@bounds.min_lon = pt.lon if pt.lon < @bounds.min_lon
@bounds.max_lat = pt.lat if pt.lat > @bounds.max_lat
Expand Down Expand Up @@ -148,43 +136,57 @@ def find_point_by_time_or_offset(indicator)
if indicator.nil?
return nil
elsif indicator.is_a?(Integer)
return self.closest_point(self.earliest_point.time + indicator)
return closest_point(@earliest_point.time + indicator)
elsif(indicator.is_a?(Time))
return self.closest_point(indicator)
return closest_point(indicator)
else
raise Exception, "find_end_point_by_time_or_offset requires an argument of type Time or Integer"
end
end

# smooths the location data in the segment (by recalculating the location as an average of 20 neighbouring points. Useful for removing noise from GPS traces.
def smooth_location_by_average(opts={})
seconds_either_side = opts[:averaging_window] || 20
earliest = (find_point_by_time_or_offset(opts[:start]) || self.earliest_point).time
latest = (find_point_by_time_or_offset(opts[:end]) || self.latest_point).time
self.points.each do |point|
next if point.time > latest || point.time < earliest

#calculate the first and last points to which the smoothing should be applied
earliest = (find_point_by_time_or_offset(opts[:start]) || @earliest_point).time
latest = (find_point_by_time_or_offset(opts[:end]) || @latest_point).time

tmp_points = []

@points.each do |point|
if point.time > latest || point.time < earliest
tmp_points.push point #add the point unaltered
next
end
lat_av = 0.to_f
lon_av = 0.to_f
alt_av = 0.to_f
n = 0
# k ranges from the time of the current point +/- 20s
(-1*seconds_either_side..seconds_either_side).each do |k|
contributing_point = self.closest_point(point.time + k)
# find the point nearest to the time offset indicated by k
contributing_point = closest_point(point.time + k)
#sum up the contributions to the average
lat_av += contributing_point.lat
lon_av += contributing_point.lon
alt_av += contributing_point.elevation
n += 1
end
point.new_lon = (lon_av) / n
point.new_elevation = (alt_av) / n
point.new_lat = (lat_av) / n
# calculate the averages
tmp_point = point.clone
tmp_point.lon = ((lon_av) / n).round(7)
tmp_point.elevation = ((alt_av) / n).round(2)
tmp_point.lat = ((lat_av) / n).round(7)
tmp_points.push tmp_point
end
last_pt = nil
@distance = 0
self.points.each do |point|
if point.time <= latest || point.time >= earliest
point.update_new_values
end
@distance += haversine_distance(last_pt, point) unless last_pt.nil?
last_pt = point
@points.clear
reset_meta_data
#now commit the averages back and recalculate the distances
tmp_points.each do |point|
append_point(point)
end
end

Expand Down
7 changes: 1 addition & 6 deletions lib/gpx/trackpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module GPX
class TrackPoint < Point
RADIUS = 6371; # earth's mean radius in km

attr_accessor :segment, :new_lat, :new_lon, :new_elevation
attr_accessor :segment


def initialize(opts = {})
Expand Down Expand Up @@ -56,10 +56,5 @@ def law_of_cosines_distance_from(p2)
(Math.acos(Math.sin(latr)*Math.sin(p2.latr) + Math.cos(latr)*Math.cos(p2.latr)*Math.cos(p2.lonr-lonr)) * RADIUS)
end

def update_new_values
self.lon = self.new_lon if self.new_lon
self.lat = self.new_lat if self.new_lat
self.elevation = self.new_elevation if self.new_elevation
end
end
end
4 changes: 2 additions & 2 deletions tests/gpx10_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class GPX10Test < Test::Unit::TestCase
class GPX10Test < Minitest::Test
GPX_FILE = File.join(File.dirname(__FILE__), "gpx_files/gpx10.gpx")

def test_read
Expand Down
4 changes: 2 additions & 2 deletions tests/gpx_file_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class GPXFileTest < Test::Unit::TestCase
class GPXFileTest < Minitest::Test

ONE_TRACK_FILE = File.join(File.dirname(__FILE__), "gpx_files/one_track.gpx")
WITH_OR_WITHOUT_ELEV_FILE = File.join(File.dirname(__FILE__), "gpx_files/with_or_without_elev.gpx")
Expand Down
4 changes: 2 additions & 2 deletions tests/magellan_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class MagellanTest < Test::Unit::TestCase
class MagellanTest < Minitest::Test
MAGELLAN_TRACK_LOG = File.join(File.dirname(__FILE__), "gpx_files/magellan_track.log")
GPX_FILE = File.join(File.dirname(__FILE__), "gpx_files/one_segment.gpx")

Expand Down
4 changes: 2 additions & 2 deletions tests/output_test.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require 'test/unit'
require 'minitest/autorun'
require 'fileutils'
require 'gpx'

class OutputTest < Test::Unit::TestCase
class OutputTest < Minitest::Test

include GPX

Expand Down
4 changes: 2 additions & 2 deletions tests/route_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class RouteTest < Test::Unit::TestCase
class RouteTest < Minitest::Test

def test_read_routes
gpx = GPX::GPXFile.new(:gpx_file => File.join(File.dirname(__FILE__), "gpx_files/routes.gpx"))
Expand Down
36 changes: 34 additions & 2 deletions tests/segment_test.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require 'test/unit'
#require 'minitest/autorun'
require 'minitest/autorun'
require 'yaml'
require 'gpx'

class SegmentTest < Test::Unit::TestCase
class SegmentTest < Minitest::Test
ONE_SEGMENT = File.join(File.dirname(__FILE__), "gpx_files/one_segment.gpx")

def setup
Expand Down Expand Up @@ -55,4 +56,35 @@ def test_segment_delete
assert_equal(39.188747, @segment.bounds.max_lat)
assert_equal(-109.007978, @segment.bounds.max_lon)
end

def test_segment_smooth
@segment.smooth_location_by_average
assert_equal(189, @segment.points.size)
assert_equal(1144433525, @segment.earliest_point.time.to_i)
assert_equal(1144437991, @segment.latest_point.time.to_i)
assert_equal(1342.58, @segment.lowest_point.elevation)
assert_equal(1479.09, @segment.highest_point.elevation)
assert_in_delta(6.458085658, @segment.distance, 0.001)
end

def test_segment_smooth_offset
@segment.smooth_location_by_average({:start => 1000, :end => 2000})
assert_equal(189, @segment.points.size)
assert_equal(1144433525, @segment.earliest_point.time.to_i)
assert_equal(1144437991, @segment.latest_point.time.to_i)
assert_equal(1334.447, @segment.lowest_point.elevation)
assert_equal(1480.087, @segment.highest_point.elevation)
assert_in_delta(6.900813095, @segment.distance, 0.001)
end

def test_segment_smooth_absolute
@segment.smooth_location_by_average({:start => Time.at(1144434520), :end => Time.at(1144435520)})
assert_equal(189, @segment.points.size)
assert_equal(1144433525, @segment.earliest_point.time.to_i)
assert_equal(1144437991, @segment.latest_point.time.to_i)
assert_equal(1334.447, @segment.lowest_point.elevation)
assert_equal(1480.087, @segment.highest_point.elevation)
assert_in_delta(6.900813095, @segment.distance, 0.001)
end

end
4 changes: 2 additions & 2 deletions tests/track_file_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class TrackFileTest < Test::Unit::TestCase
class TrackFileTest < Minitest::Test
TRACK_FILE = File.join(File.dirname(__FILE__), "gpx_files/tracks.gpx")
OTHER_TRACK_FILE = File.join(File.dirname(__FILE__), "gpx_files/arches.gpx")

Expand Down
4 changes: 2 additions & 2 deletions tests/track_point_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test/unit'
require 'minitest/autorun'
require 'gpx'

class TrackPointTest < Test::Unit::TestCase
class TrackPointTest < Minitest::Test
def setup
@point1 = GPX::TrackPoint.new({
:lat => 37.7985474,
Expand Down
Loading

0 comments on commit fbe8c68

Please sign in to comment.