Adding some new unit tests and fixing several file export bugs reported by Jochen Topf.
New unit tests also uncovered a bug where the number of trackpoints reported in a file was twice the actual number.master
parent
ef1eac8cbb
commit
3abba74eef
|
@ -22,7 +22,7 @@
|
|||
#++
|
||||
module GPX
|
||||
class GPXFile < Base
|
||||
attr_reader :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :distance, :duration, :average_speed, :ns
|
||||
attr_accessor :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :duration, :ns, :time, :name
|
||||
|
||||
|
||||
# This initializer can be used to create a new GPXFile from an existing
|
||||
|
@ -76,6 +76,9 @@ module GPX
|
|||
get_bounds = true
|
||||
end
|
||||
|
||||
@time = Time.parse(@xml.find("//gpx:gpx/gpx:metadata/gpx:time", @ns).first.content) rescue nil
|
||||
@name = @xml.find("//gpx:gpx/gpx:metadata/gpx:name", @ns).first.content rescue nil
|
||||
|
||||
@tracks = []
|
||||
@xml.find("//gpx:gpx/gpx:trk", @ns).each do |trk|
|
||||
trk = Track.new(:element => trk, :gpx_file => self)
|
||||
|
@ -98,6 +101,9 @@ module GPX
|
|||
calculate_duration
|
||||
end
|
||||
end
|
||||
@tracks ||= []
|
||||
@routes ||= []
|
||||
@waypoints ||= []
|
||||
end
|
||||
|
||||
def get_bounds_attr_value(el, possible_names)
|
||||
|
@ -199,7 +205,7 @@ module GPX
|
|||
|
||||
# Serialize the current GPXFile to a gpx file named <filename>.
|
||||
# If the file does not exist, it is created. If it does exist, it is overwritten.
|
||||
def write(filename)
|
||||
def write(filename, update_time = true)
|
||||
|
||||
doc = Document.new
|
||||
doc.root = Node.new('gpx')
|
||||
|
@ -216,7 +222,10 @@ module GPX
|
|||
meta_data_elem << name_elem
|
||||
|
||||
time_elem = Node.new('time')
|
||||
time_elem << Time.now.xmlschema
|
||||
|
||||
@time = Time.now if(@time.nil? or update_time)
|
||||
time_elem << @time.xmlschema
|
||||
|
||||
meta_data_elem << time_elem
|
||||
|
||||
meta_data_elem << bounds.to_xml
|
||||
|
|
|
@ -88,7 +88,7 @@ module GPX
|
|||
|
||||
# Convert this point to a XML::Node.
|
||||
def to_xml(elem_name = 'trkpt')
|
||||
pt = Node.new('trkpt')
|
||||
pt = Node.new(elem_name)
|
||||
pt['lat'] = lat.to_s
|
||||
pt['lon'] = lon.to_s
|
||||
unless time.nil?
|
||||
|
|
|
@ -27,10 +27,11 @@ module GPX
|
|||
# automatically logging your progress at regular intervals.
|
||||
class Route < Base
|
||||
|
||||
attr_reader :points, :name, :gpx_file
|
||||
attr_accessor :points, :name, :gpx_file
|
||||
|
||||
# Initialize a Route from a XML::Node.
|
||||
def initialize(opts = {})
|
||||
if(opts[:gpx_file] and opts[:element])
|
||||
rte_element = opts[:element]
|
||||
@gpx_file = opts[:gpx_file]
|
||||
@name = rte_element.find("child::gpx:name", @gpx_file.ns).first.content
|
||||
|
@ -38,6 +39,10 @@ module GPX
|
|||
rte_element.find("child::gpx:rtept", @gpx_file.ns).each do |point|
|
||||
@points << Point.new(:element => point, :gpx_file => @gpx_file)
|
||||
end
|
||||
else
|
||||
@points = (opts[:points] or [])
|
||||
@name = (opts[:name])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ module GPX
|
|||
seg = Segment.new(:element => seg_element, :track => self, :gpx_file => @gpx_file)
|
||||
update_meta_data(seg)
|
||||
@segments << seg
|
||||
@points.concat(seg.points) unless seg.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -42,10 +42,19 @@ module GPX
|
|||
|
||||
# Initializes a waypoint from a XML::Node.
|
||||
def initialize(opts = {})
|
||||
if(opts[:element] and opts[:gpx_file])
|
||||
wpt_elem = opts[:element]
|
||||
@gpx_file = opts[:gpx_file]
|
||||
super(:element => wpt_elem, :gpx_file => @gpx_file)
|
||||
instantiate_with_text_elements(wpt_elem, SUB_ELEMENTS, @gpx_file.ns)
|
||||
else
|
||||
opts.each do |key, value|
|
||||
assignment_method = "#{key}="
|
||||
if self.respond_to?(assignment_method)
|
||||
self.send(assignment_method, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Prints out a friendly summary of this track (sans points). Useful for
|
||||
|
@ -67,22 +76,19 @@ module GPX
|
|||
# Converts a waypoint to a XML::Node.
|
||||
def to_xml
|
||||
wpt = Node.new('wpt')
|
||||
wpt.attributes['lat'] = lat
|
||||
wpt.attributes['lon'] = lon
|
||||
if self.respond_to? :name
|
||||
name_elem = Node.new('name')
|
||||
name_elem << self.name
|
||||
wpt << name_elem
|
||||
wpt['lat'] = lat.to_s
|
||||
wpt['lon'] = lon.to_s
|
||||
SUB_ELEMENTS.each do |sub_element_name|
|
||||
if(self.respond_to?(sub_element_name) and (!self.send(sub_element_name).nil?))
|
||||
sub_elem_node = Node.new(sub_element_name)
|
||||
sub_elem_node << self.send(sub_element_name)
|
||||
wpt << sub_elem_node
|
||||
end
|
||||
if self.respond_to? :sym
|
||||
sym_elem = Node.new('sym')
|
||||
sym_elem << self.sym
|
||||
wpt << sym_elem
|
||||
end
|
||||
if self.respond_to? :ele
|
||||
elev_elem = Node.new('ele')
|
||||
elev_elem << self.ele
|
||||
wpt << elev_elem
|
||||
unless(self.elevation.nil?)
|
||||
ele_node = Node.new('ele')
|
||||
ele_node << self.elevation
|
||||
wpt << ele_node
|
||||
end
|
||||
wpt
|
||||
end
|
||||
|
|
|
@ -2,8 +2,40 @@ require 'test/unit'
|
|||
require File.dirname(__FILE__) + '/../lib/gpx'
|
||||
|
||||
class GPXFileTest < Test::Unit::TestCase
|
||||
|
||||
ONE_TRACK_FILE = File.join(File.dirname(__FILE__), "gpx_files/one_track.gpx")
|
||||
def test_load_data
|
||||
GPX::GPXFile.new(:gpx_data => open(ONE_TRACK_FILE).read)
|
||||
BIG_FILE = File.join(File.dirname(__FILE__), "gpx_files/big.gpx")
|
||||
|
||||
def test_load_data_from_string
|
||||
gpx_file = GPX::GPXFile.new(:gpx_data => open(ONE_TRACK_FILE).read)
|
||||
assert_equal(1, gpx_file.tracks.size)
|
||||
assert_equal(8, gpx_file.tracks.first.segments.size)
|
||||
assert_equal("ACTIVE LOG", gpx_file.tracks.first.name)
|
||||
assert_equal("active_log.gpx", gpx_file.name)
|
||||
assert_equal("2006-04-08T16:44:28Z", gpx_file.time.xmlschema)
|
||||
assert_equal(38.681488, gpx_file.bounds.min_lat)
|
||||
assert_equal(-109.606948, gpx_file.bounds.min_lon)
|
||||
assert_equal(38.791759, gpx_file.bounds.max_lat)
|
||||
assert_equal(-109.447045, gpx_file.bounds.max_lon)
|
||||
end
|
||||
|
||||
def test_load_data_from_file
|
||||
gpx_file = GPX::GPXFile.new(:gpx_file => ONE_TRACK_FILE)
|
||||
assert_equal(1, gpx_file.tracks.size)
|
||||
assert_equal(8, gpx_file.tracks.first.segments.size)
|
||||
assert_equal("ACTIVE LOG", gpx_file.tracks.first.name)
|
||||
assert_equal("active_log.gpx", gpx_file.name)
|
||||
assert_equal("2006-04-08T16:44:28Z", gpx_file.time.xmlschema)
|
||||
assert_equal(38.681488, gpx_file.bounds.min_lat)
|
||||
assert_equal(-109.606948, gpx_file.bounds.min_lon)
|
||||
assert_equal(38.791759, gpx_file.bounds.max_lat)
|
||||
assert_equal(-109.447045, gpx_file.bounds.max_lon)
|
||||
end
|
||||
|
||||
def test_big_file
|
||||
gpx_file = GPX::GPXFile.new(:gpx_file => BIG_FILE)
|
||||
assert_equal(1, gpx_file.tracks.size)
|
||||
assert_equal(7968, gpx_file.tracks.first.points.size)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,114 @@
|
|||
require 'test/unit'
|
||||
require File.dirname(__FILE__) + '/../lib/gpx'
|
||||
|
||||
class OutputTest < Test::Unit::TestCase
|
||||
|
||||
include GPX
|
||||
|
||||
def test_new_gpx_file_from_scratch
|
||||
gpx_file = GPXFile.new
|
||||
|
||||
track = Track.new(:name => "My First Track")
|
||||
segment = Segment.new
|
||||
|
||||
track_point_data = [
|
||||
{:lat => 40.036926, :lon =>-105.253487, :time => Time.parse('2005-12-31T22:01:24Z'), :elevation => 1737.24},
|
||||
{:lat => 40.036604, :lon =>-105.253487, :time => Time.parse("2005-12-31T22:02:01Z"), :elevation => 1738.682},
|
||||
{:lat => 40.036347, :lon =>-105.253830, :time => Time.parse("2005-12-31T22:02:08Z"), :elevation => 1738.682},
|
||||
{:lat => 40.035574, :lon =>-105.254045, :time => Time.parse("2005-12-31T22:02:20Z"), :elevation => 1737.24},
|
||||
{:lat => 40.035467, :lon =>-105.254366, :time => Time.parse("2005-12-31T22:02:29Z"), :elevation => 1735.798},
|
||||
{:lat => 40.035317, :lon =>-105.254388, :time => Time.parse("2005-12-31T22:02:33Z"), :elevation => 1735.798},
|
||||
{:lat => 40.035274, :lon =>-105.254431, :time => Time.parse("2005-12-31T22:02:49Z"), :elevation => 1736.278},
|
||||
{:lat => 40.035274, :lon =>-105.254431, :time => Time.parse("2005-12-31T22:02:54Z"), :elevation => 1739.643},
|
||||
{:lat => 40.035317, :lon =>-105.254431, :time => Time.parse("2005-12-31T22:05:08Z"), :elevation => 1732.433},
|
||||
{:lat => 40.035317, :lon =>-105.254431, :time => Time.parse("2005-12-31T22:05:09Z"), :elevation => 1726.665}]
|
||||
|
||||
track_point_data.each do |trk_pt_hash|
|
||||
segment.points << TrackPoint.new(trk_pt_hash)
|
||||
end
|
||||
|
||||
track.segments << segment
|
||||
gpx_file.tracks << track
|
||||
|
||||
waypoint_data = [
|
||||
{:lat => 39.997298, :lon => -105.292674, :name => 'GRG-CA', :sym => 'Waypoint', :elevation => 1766.535},
|
||||
{:lat => 33.330190, :lon => -111.946110, :name => 'GRMPHX', :sym => 'Waypoint', :elevation => 361.0981,
|
||||
:cmt => "Hey here's a comment.", :desc => "Somewhere in my backyard.", :fix => '3d', :sat => "8", :hdop => "50.5", :vdop => "6.8", :pdop => "7.6"},
|
||||
{:lat => 25.061783, :lon => 121.640267, :name => 'GRMTWN', :sym => 'Waypoint', :elevation => 38.09766},
|
||||
{:lat => 39.999840, :lon => -105.214696, :name => 'SBDR', :sym => 'Waypoint', :elevation => 1612.965},
|
||||
{:lat => 39.989739, :lon => -105.295285, :name => 'TO', :sym => 'Waypoint', :elevation => 2163.556},
|
||||
{:lat => 40.035301, :lon => -105.254443, :name => 'VICS', :sym => 'Waypoint', :elevation => 1535.34}
|
||||
]
|
||||
|
||||
waypoint_data.each do |wpt_hash|
|
||||
gpx_file.waypoints << Waypoint.new(wpt_hash)
|
||||
end
|
||||
|
||||
route_point_data = [
|
||||
{:lat => 40.035467, :lon =>-105.254366, :time => Time.parse("2005-12-31T22:02:29Z"), :elevation => 1735.798},
|
||||
{:lat => 40.035317, :lon =>-105.254388, :time => Time.parse("2005-12-31T22:02:33Z"), :elevation => 1735.798},
|
||||
{:lat => 40.035274, :lon =>-105.254431, :time => Time.parse("2005-12-31T22:02:49Z"), :elevation => 1736.278} ]
|
||||
|
||||
route = Route.new()
|
||||
route_point_data.each do |rte_pt_hash|
|
||||
route.points << Point.new(rte_pt_hash)
|
||||
end
|
||||
|
||||
gpx_file.routes << route
|
||||
|
||||
gpx_file.write(output_file(name_of_test))
|
||||
|
||||
|
||||
written_gpx_file = GPXFile.new(:gpx_file => output_file(name_of_test))
|
||||
|
||||
assert_equal(File.basename(output_file(name_of_test)), written_gpx_file.name)
|
||||
assert_equal(1, written_gpx_file.tracks.size)
|
||||
assert_equal(1, written_gpx_file.tracks[0].segments.size)
|
||||
assert_equal(track_point_data.size, written_gpx_file.tracks[0].segments[0].points.size)
|
||||
assert_equal(track_point_data.size, written_gpx_file.tracks[0].points.size)
|
||||
|
||||
# Make sure each point in the segment has the attributes it was initialized with
|
||||
written_segment = written_gpx_file.tracks[0].segments[0]
|
||||
track_point_data.each_with_index do |trk_pt_hash, index|
|
||||
trk_pt_hash.each do |key, value|
|
||||
assert_equal(value, written_segment.points[index].send(key))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Make sure the one route has the attributes we initialized it with
|
||||
assert_equal(1, written_gpx_file.routes.size)
|
||||
written_route = written_gpx_file.routes[0]
|
||||
assert_equal(route_point_data.size, written_route.points.size)
|
||||
route_point_data.each_with_index do |rte_pt_hash, index|
|
||||
rte_pt_hash.each do |key, value|
|
||||
assert_equal(value, written_route.points[index].send(key))
|
||||
end
|
||||
end
|
||||
|
||||
# Make sure the waypoints have all of the attributes we initialized them with
|
||||
written_waypoints = written_gpx_file.waypoints
|
||||
assert_equal(waypoint_data.size, written_waypoints.size)
|
||||
waypoint_data.each_with_index do |wpt_hash, index|
|
||||
wpt_hash.each do |key, value|
|
||||
assert_equal(value, written_waypoints[index].send(key.to_s), key)
|
||||
end
|
||||
end
|
||||
|
||||
expected_value = sprintf(THE_WORKS, gpx_file.time.xmlschema)
|
||||
assert_equal(expected_value, IO.read(output_file(name_of_test)))
|
||||
|
||||
end
|
||||
|
||||
def name_of_test
|
||||
caller[0] =~ /`test_([^']*)'/ and $1
|
||||
end
|
||||
|
||||
def output_file(test_name)
|
||||
File.join(File.dirname(__FILE__), "output/#{test_name}.gpx")
|
||||
end
|
||||
|
||||
THE_WORKS = "<?xml version=\"1.0\"?>\n<gpx xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/1\" version=\"1.1\" creator=\"GPX RubyGem 0.1 Copyright 2006 Doug Fales -- http://walkingboss.com\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n <metadata>\n <name>new_gpx_file_from_scratch.gpx</name>\n <time>%s</time>\n <bounds minlat=\"90.0\" minlon=\"180.0\" maxlat=\"-90.0\" maxlon=\"-180.0\"/>\n </metadata>\n <trk>\n <name/>\n <trkseg>\n <trkpt lat=\"40.036926\" lon=\"-105.253487\">\n <time>2005-12-31T22:01:24Z</time>\n <ele>1737.24</ele>\n </trkpt>\n <trkpt lat=\"40.036604\" lon=\"-105.253487\">\n <time>2005-12-31T22:02:01Z</time>\n <ele>1738.682</ele>\n </trkpt>\n <trkpt lat=\"40.036347\" lon=\"-105.25383\">\n <time>2005-12-31T22:02:08Z</time>\n <ele>1738.682</ele>\n </trkpt>\n <trkpt lat=\"40.035574\" lon=\"-105.254045\">\n <time>2005-12-31T22:02:20Z</time>\n <ele>1737.24</ele>\n </trkpt>\n <trkpt lat=\"40.035467\" lon=\"-105.254366\">\n <time>2005-12-31T22:02:29Z</time>\n <ele>1735.798</ele>\n </trkpt>\n <trkpt lat=\"40.035317\" lon=\"-105.254388\">\n <time>2005-12-31T22:02:33Z</time>\n <ele>1735.798</ele>\n </trkpt>\n <trkpt lat=\"40.035274\" lon=\"-105.254431\">\n <time>2005-12-31T22:02:49Z</time>\n <ele>1736.278</ele>\n </trkpt>\n <trkpt lat=\"40.035274\" lon=\"-105.254431\">\n <time>2005-12-31T22:02:54Z</time>\n <ele>1739.643</ele>\n </trkpt>\n <trkpt lat=\"40.035317\" lon=\"-105.254431\">\n <time>2005-12-31T22:05:08Z</time>\n <ele>1732.433</ele>\n </trkpt>\n <trkpt lat=\"40.035317\" lon=\"-105.254431\">\n <time>2005-12-31T22:05:09Z</time>\n <ele>1726.665</ele>\n </trkpt>\n </trkseg>\n </trk>\n <wpt lat=\"39.997298\" lon=\"-105.292674\">\n <name>GRG-CA</name>\n <sym>Waypoint</sym>\n <ele>1766.535</ele>\n </wpt>\n <wpt lat=\"33.33019\" lon=\"-111.94611\">\n <name>GRMPHX</name>\n <cmt>Hey here's a comment.</cmt>\n <desc>Somewhere in my backyard.</desc>\n <sym>Waypoint</sym>\n <fix>3d</fix>\n <sat>8</sat>\n <hdop>50.5</hdop>\n <vdop>6.8</vdop>\n <pdop>7.6</pdop>\n <ele>361.0981</ele>\n </wpt>\n <wpt lat=\"25.061783\" lon=\"121.640267\">\n <name>GRMTWN</name>\n <sym>Waypoint</sym>\n <ele>38.09766</ele>\n </wpt>\n <wpt lat=\"39.99984\" lon=\"-105.214696\">\n <name>SBDR</name>\n <sym>Waypoint</sym>\n <ele>1612.965</ele>\n </wpt>\n <wpt lat=\"39.989739\" lon=\"-105.295285\">\n <name>TO</name>\n <sym>Waypoint</sym>\n <ele>2163.556</ele>\n </wpt>\n <wpt lat=\"40.035301\" lon=\"-105.254443\">\n <name>VICS</name>\n <sym>Waypoint</sym>\n <ele>1535.34</ele>\n </wpt>\n <rte>\n <name/>\n <rtept lat=\"40.035467\" lon=\"-105.254366\">\n <time>2005-12-31T22:02:29Z</time>\n <ele>1735.798</ele>\n </rtept>\n <rtept lat=\"40.035317\" lon=\"-105.254388\">\n <time>2005-12-31T22:02:33Z</time>\n <ele>1735.798</ele>\n </rtept>\n <rtept lat=\"40.035274\" lon=\"-105.254431\">\n <time>2005-12-31T22:02:49Z</time>\n <ele>1736.278</ele>\n </rtept>\n </rte>\n</gpx>\n"
|
||||
|
||||
end
|
|
@ -11,7 +11,7 @@ class TrackTest < Test::Unit::TestCase
|
|||
|
||||
def test_track_read
|
||||
assert_equal("ACTIVE LOG", @track.name)
|
||||
assert_equal( 364, @track.points.size)
|
||||
assert_equal( 182, @track.points.size)
|
||||
assert_equal(8, @track.segments.size)
|
||||
assert_equal("3.07249668492626", @track.distance.to_s)
|
||||
assert_equal(1267.155, @track.lowest_point.elevation)
|
||||
|
|
Loading…
Reference in New Issue