gpx 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +4 -0
- data/.rubocop.yml +165 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +8 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/Rakefile +15 -12
- data/bin/gpx_distance +3 -6
- data/bin/gpx_smooth +20 -24
- data/gpx.gemspec +12 -11
- data/lib/gpx.rb +11 -34
- data/lib/gpx/bounds.rb +10 -31
- data/lib/gpx/gpx.rb +2 -26
- data/lib/gpx/gpx_file.rb +112 -108
- data/lib/gpx/magellan_track_log.rb +32 -66
- data/lib/gpx/point.rb +18 -35
- data/lib/gpx/route.rb +7 -31
- data/lib/gpx/segment.rb +56 -88
- data/lib/gpx/track.rb +31 -42
- data/lib/gpx/track_point.rb +30 -0
- data/lib/gpx/version.rb +1 -1
- data/lib/gpx/waypoint.rb +7 -34
- data/tests/gpx10_test.rb +5 -6
- data/tests/gpx_file_test.rb +29 -19
- data/tests/gpx_files/with_empty_tracks.gpx +72 -0
- data/tests/magellan_test.rb +10 -11
- data/tests/output_test.rb +92 -95
- data/tests/route_test.rb +25 -32
- data/tests/segment_test.rb +93 -94
- data/tests/track_file_test.rb +47 -70
- data/tests/track_point_test.rb +20 -11
- data/tests/track_test.rb +71 -61
- data/tests/waypoint_test.rb +44 -48
- metadata +29 -13
- data/lib/gpx/trackpoint.rb +0 -60
data/lib/gpx/bounds.rb
CHANGED
@@ -1,58 +1,38 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2006 Doug Fales
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
1
|
module GPX
|
24
2
|
class Bounds < Base
|
25
|
-
attr_accessor :min_lat, :max_lat, :max_lon, :min_lon
|
3
|
+
attr_accessor :min_lat, :max_lat, :max_lon, :min_lon
|
26
4
|
|
27
5
|
# Creates a new bounds object with the passed-in min and max longitudes
|
28
6
|
# and latitudes.
|
29
|
-
def initialize(opts = { :
|
30
|
-
@min_lat
|
31
|
-
@
|
7
|
+
def initialize(opts = { min_lat: 90.0, max_lat: -90.0, min_lon: 180.0, max_lon: -180.0 })
|
8
|
+
@min_lat = opts[:min_lat].to_f
|
9
|
+
@max_lat = opts[:max_lat].to_f
|
10
|
+
@min_lon = opts[:min_lon].to_f
|
11
|
+
@max_lon = opts[:max_lon].to_f
|
32
12
|
end
|
33
13
|
|
34
14
|
# Returns the middle latitude.
|
35
15
|
def center_lat
|
36
|
-
distance = (max_lat - min_lat)/2.0
|
16
|
+
distance = (max_lat - min_lat) / 2.0
|
37
17
|
(min_lat + distance)
|
38
18
|
end
|
39
19
|
|
40
20
|
# Returns the middle longitude.
|
41
21
|
def center_lon
|
42
|
-
distance = (max_lon - min_lon)/2.0
|
22
|
+
distance = (max_lon - min_lon) / 2.0
|
43
23
|
(min_lon + distance)
|
44
24
|
end
|
45
25
|
|
46
26
|
# Returns true if the pt is within these bounds.
|
47
27
|
def contains?(pt)
|
48
|
-
(pt.lat >=
|
28
|
+
((pt.lat >= min_lat) && (pt.lat <= max_lat) && (pt.lon >= min_lon) && (pt.lon <= max_lon))
|
49
29
|
end
|
50
30
|
|
51
31
|
# Adds an item to itself, expanding its min/max lat/lon as needed to
|
52
32
|
# contain the given item. The item can be either another instance of
|
53
33
|
# Bounds or a Point.
|
54
34
|
def add(item)
|
55
|
-
if
|
35
|
+
if item.respond_to?(:lat) && item.respond_to?(:lon)
|
56
36
|
@min_lat = item.lat if item.lat < @min_lat
|
57
37
|
@min_lon = item.lon if item.lon < @min_lon
|
58
38
|
@max_lat = item.lat if item.lat > @max_lat
|
@@ -69,6 +49,5 @@ module GPX
|
|
69
49
|
def to_s
|
70
50
|
"min_lat: #{min_lat} min_lon: #{min_lon} max_lat: #{max_lat} max_lon: #{max_lon}"
|
71
51
|
end
|
72
|
-
|
73
52
|
end
|
74
53
|
end
|
data/lib/gpx/gpx.rb
CHANGED
@@ -1,25 +1,3 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2006 Doug Fales
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
1
|
module GPX
|
24
2
|
# A common base class which provides a useful initializer method to many
|
25
3
|
# class in the GPX library.
|
@@ -33,14 +11,12 @@ module GPX
|
|
33
11
|
# attributes to this method.
|
34
12
|
def instantiate_with_text_elements(parent, text_elements)
|
35
13
|
text_elements.each do |el|
|
36
|
-
child_xpath =
|
14
|
+
child_xpath = el.to_s
|
37
15
|
unless parent.at(child_xpath).nil?
|
38
16
|
val = parent.at(child_xpath).inner_text
|
39
|
-
|
17
|
+
send("#{el}=", val)
|
40
18
|
end
|
41
19
|
end
|
42
|
-
|
43
20
|
end
|
44
|
-
|
45
21
|
end
|
46
22
|
end
|
data/lib/gpx/gpx_file.rb
CHANGED
@@ -1,28 +1,7 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2006 Doug Fales
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
1
|
module GPX
|
24
2
|
class GPXFile < Base
|
25
|
-
attr_accessor :tracks,
|
3
|
+
attr_accessor :tracks,
|
4
|
+
:routes, :waypoints, :bounds, :lowest_point, :highest_point, :duration, :ns, :time, :name, :version, :creator, :description, :moving_duration
|
26
5
|
|
27
6
|
DEFAULT_CREATOR = "GPX RubyGem #{GPX::VERSION} -- http://dougfales.github.io/gpx/".freeze
|
28
7
|
|
@@ -47,7 +26,10 @@ module GPX
|
|
47
26
|
@duration = 0
|
48
27
|
@attributes = {}
|
49
28
|
@namespace_defs = []
|
50
|
-
|
29
|
+
@tracks = []
|
30
|
+
@time = nil
|
31
|
+
|
32
|
+
if opts[:gpx_file] || opts[:gpx_data]
|
51
33
|
if opts[:gpx_file]
|
52
34
|
gpx_file = opts[:gpx_file]
|
53
35
|
gpx_file = File.open(gpx_file) unless gpx_file.is_a?(File)
|
@@ -59,41 +41,53 @@ module GPX
|
|
59
41
|
gpx_element = @xml.at('gpx')
|
60
42
|
@attributes = gpx_element.attributes
|
61
43
|
@namespace_defs = gpx_element.namespace_definitions
|
62
|
-
#$stderr.puts gpx_element.attributes.sort.inspect
|
63
|
-
#$stderr.puts @xmlns.inspect
|
64
|
-
#$stderr.puts @xsi.inspect
|
65
44
|
@version = gpx_element['version']
|
66
45
|
reset_meta_data
|
67
|
-
bounds_element = (
|
46
|
+
bounds_element = (begin
|
47
|
+
@xml.at('metadata/bounds')
|
48
|
+
rescue StandardError
|
49
|
+
nil
|
50
|
+
end)
|
68
51
|
if bounds_element
|
69
|
-
@bounds.min_lat = get_bounds_attr_value(bounds_element, %w
|
70
|
-
@bounds.min_lon = get_bounds_attr_value(bounds_element, %w
|
71
|
-
@bounds.max_lat = get_bounds_attr_value(bounds_element, %w
|
72
|
-
@bounds.max_lon = get_bounds_attr_value(bounds_element, %w
|
52
|
+
@bounds.min_lat = get_bounds_attr_value(bounds_element, %w[min_lat minlat minLat])
|
53
|
+
@bounds.min_lon = get_bounds_attr_value(bounds_element, %w[min_lon minlon minLon])
|
54
|
+
@bounds.max_lat = get_bounds_attr_value(bounds_element, %w[max_lat maxlat maxLat])
|
55
|
+
@bounds.max_lon = get_bounds_attr_value(bounds_element, %w[max_lon maxlon maxLon])
|
73
56
|
else
|
74
57
|
get_bounds = true
|
75
58
|
end
|
76
59
|
|
77
|
-
@time =
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
60
|
+
@time = begin
|
61
|
+
Time.parse(@xml.at('metadata/time').inner_text)
|
62
|
+
rescue StandardError
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
@name = begin
|
66
|
+
@xml.at('metadata/name').inner_text
|
67
|
+
rescue StandardError
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
@description = begin
|
71
|
+
@xml.at('metadata/desc').inner_text
|
72
|
+
rescue StandardError
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
@xml.search('trk').each do |trk|
|
76
|
+
trk = Track.new(element: trk, gpx_file: self)
|
83
77
|
update_meta_data(trk, get_bounds)
|
84
78
|
@tracks << trk
|
85
79
|
end
|
86
80
|
@waypoints = []
|
87
|
-
@xml.search(
|
81
|
+
@xml.search('wpt').each { |wpt| @waypoints << Waypoint.new(element: wpt, gpx_file: self) }
|
88
82
|
@routes = []
|
89
|
-
@xml.search(
|
90
|
-
@tracks.delete_if
|
83
|
+
@xml.search('rte').each { |rte| @routes << Route.new(element: rte, gpx_file: self) }
|
84
|
+
@tracks.delete_if(&:empty?)
|
91
85
|
|
92
86
|
calculate_duration
|
93
87
|
else
|
94
88
|
reset_meta_data
|
95
|
-
opts.each { |attr_name, value| instance_variable_set("@#{attr_name
|
96
|
-
unless
|
89
|
+
opts.each { |attr_name, value| instance_variable_set("@#{attr_name}", value) }
|
90
|
+
unless @tracks.nil? || @tracks.size.zero?
|
97
91
|
@tracks.each { |trk| update_meta_data(trk) }
|
98
92
|
calculate_duration
|
99
93
|
end
|
@@ -109,19 +103,23 @@ module GPX
|
|
109
103
|
result = el[name]
|
110
104
|
break unless result.nil?
|
111
105
|
end
|
112
|
-
|
106
|
+
(begin
|
107
|
+
result.to_f
|
108
|
+
rescue StandardError
|
109
|
+
nil
|
110
|
+
end)
|
113
111
|
end
|
114
112
|
|
115
113
|
# Returns the distance, in kilometers, meters, or miles, of all of the
|
116
114
|
# tracks and segments contained in this GPXFile.
|
117
|
-
def distance(opts = { :
|
115
|
+
def distance(opts = { units: 'kilometers' })
|
118
116
|
case opts[:units]
|
119
117
|
when /kilometers/i
|
120
|
-
|
118
|
+
@distance
|
121
119
|
when /meters/i
|
122
|
-
|
120
|
+
(@distance * 1000)
|
123
121
|
when /miles/i
|
124
|
-
|
122
|
+
(@distance * 0.62)
|
125
123
|
end
|
126
124
|
end
|
127
125
|
|
@@ -129,14 +127,14 @@ module GPX
|
|
129
127
|
# GPXFile. The calculation is based on the total distance divided by the
|
130
128
|
# sum of duration of all segments of all tracks
|
131
129
|
# (not taking into accounting pause time).
|
132
|
-
def average_speed(opts = { :
|
130
|
+
def average_speed(opts = { units: 'kilometers' })
|
133
131
|
case opts[:units]
|
134
132
|
when /kilometers/i
|
135
|
-
|
133
|
+
distance / (moving_duration / 3600.0)
|
136
134
|
when /meters/i
|
137
|
-
|
135
|
+
(distance * 1000) / (moving_duration / 3600.0)
|
138
136
|
when /miles/i
|
139
|
-
|
137
|
+
(distance * 0.62) / (moving_duration / 3600.0)
|
140
138
|
end
|
141
139
|
end
|
142
140
|
|
@@ -176,7 +174,7 @@ module GPX
|
|
176
174
|
keep_tracks << trk
|
177
175
|
end
|
178
176
|
end
|
179
|
-
@tracks =
|
177
|
+
@tracks = keep_tracks
|
180
178
|
routes.each { |rte| rte.delete_area(area) }
|
181
179
|
waypoints.each { |wpt| wpt.delete_area(area) }
|
182
180
|
end
|
@@ -196,8 +194,8 @@ module GPX
|
|
196
194
|
# you modify the GPX data (i.e. by adding or deleting points) and you
|
197
195
|
# want the meta data to accurately reflect the new data.
|
198
196
|
def update_meta_data(trk, get_bounds = true)
|
199
|
-
@lowest_point
|
200
|
-
@highest_point
|
197
|
+
@lowest_point = trk.lowest_point if @lowest_point.nil? || (!trk.lowest_point.nil? && (trk.lowest_point.elevation < @lowest_point.elevation))
|
198
|
+
@highest_point = trk.highest_point if @highest_point.nil? || (!trk.highest_point.nil? && (trk.highest_point.elevation > @highest_point.elevation))
|
201
199
|
@bounds.add(trk.bounds) if get_bounds
|
202
200
|
@distance += trk.distance
|
203
201
|
@moving_duration += trk.moving_duration
|
@@ -206,14 +204,14 @@ module GPX
|
|
206
204
|
# Serialize the current GPXFile to a gpx file named <filename>.
|
207
205
|
# If the file does not exist, it is created. If it does exist, it is overwritten.
|
208
206
|
def write(filename, update_time = true)
|
209
|
-
@time = Time.now if
|
207
|
+
@time = Time.now if @time.nil? || update_time
|
210
208
|
@name ||= File.basename(filename)
|
211
209
|
doc = generate_xml_doc
|
212
210
|
File.open(filename, 'w+') { |f| f.write(doc.to_xml) }
|
213
211
|
end
|
214
212
|
|
215
213
|
def to_s(update_time = true)
|
216
|
-
@time = Time.now if
|
214
|
+
@time = Time.now if @time.nil? || update_time
|
217
215
|
doc = generate_xml_doc
|
218
216
|
doc.to_xml
|
219
217
|
end
|
@@ -231,117 +229,123 @@ module GPX
|
|
231
229
|
end
|
232
230
|
|
233
231
|
private
|
232
|
+
|
234
233
|
def attributes_and_nsdefs_as_gpx_attributes
|
235
|
-
|
234
|
+
# $stderr.puts @namespace_defs.inspect
|
236
235
|
gpx_header = {}
|
237
|
-
@attributes.each do |k,v|
|
236
|
+
@attributes.each do |k, v|
|
238
237
|
k = v.namespace.prefix + ':' + k if v.namespace
|
239
238
|
gpx_header[k] = v.value
|
240
|
-
end
|
239
|
+
end
|
241
240
|
|
242
241
|
@namespace_defs.each do |nsd|
|
243
242
|
tag = 'xmlns'
|
244
|
-
if nsd.prefix
|
245
|
-
tag += ':' + nsd.prefix
|
246
|
-
end
|
243
|
+
tag += ':' + nsd.prefix if nsd.prefix
|
247
244
|
gpx_header[tag] = nsd.href
|
248
245
|
end
|
249
|
-
|
246
|
+
gpx_header
|
250
247
|
end
|
251
|
-
|
248
|
+
|
252
249
|
def generate_xml_doc
|
253
250
|
@version ||= '1.1'
|
254
|
-
version_dir = version.
|
251
|
+
version_dir = version.tr('.', '/')
|
255
252
|
|
256
253
|
gpx_header = attributes_and_nsdefs_as_gpx_attributes
|
257
|
-
|
258
|
-
gpx_header['version'] = @version.to_s if !gpx_header['version']
|
259
|
-
gpx_header['creator'] = DEFAULT_CREATOR if !gpx_header['creator']
|
260
|
-
gpx_header['xsi:schemaLocation'] = "http://www.topografix.com/GPX/#{version_dir} http://www.topografix.com/GPX/#{version_dir}/gpx.xsd" if !gpx_header['xsi:schemaLocation']
|
261
|
-
gpx_header['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance" if !gpx_header['xsi'] and !gpx_header['xmlns:xsi']
|
262
|
-
|
263
|
-
#$stderr.puts gpx_header.keys.inspect
|
264
254
|
|
255
|
+
gpx_header['version'] = @version.to_s unless gpx_header['version']
|
256
|
+
gpx_header['creator'] = DEFAULT_CREATOR unless gpx_header['creator']
|
257
|
+
gpx_header['xsi:schemaLocation'] = "http://www.topografix.com/GPX/#{version_dir} http://www.topografix.com/GPX/#{version_dir}/gpx.xsd" unless gpx_header['xsi:schemaLocation']
|
258
|
+
gpx_header['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance' if !gpx_header['xsi'] && !gpx_header['xmlns:xsi']
|
259
|
+
|
260
|
+
# $stderr.puts gpx_header.keys.inspect
|
261
|
+
|
262
|
+
# rubocop:disable Metrics/BlockLength
|
265
263
|
doc = Nokogiri::XML::Builder.new do |xml|
|
266
|
-
xml.gpx(gpx_header)
|
267
|
-
|
268
|
-
|
269
|
-
|
264
|
+
xml.gpx(gpx_header) do
|
265
|
+
# version 1.0 of the schema doesn't support the metadata element, so push them straight to the root 'gpx' element
|
266
|
+
if @version == '1.0'
|
267
|
+
xml.name @name
|
268
|
+
xml.time @time.xmlschema
|
269
|
+
xml.bound(
|
270
|
+
minlat: bounds.min_lat,
|
271
|
+
minlon: bounds.min_lon,
|
272
|
+
maxlat: bounds.max_lat,
|
273
|
+
maxlon: bounds.max_lon
|
274
|
+
)
|
275
|
+
else
|
276
|
+
xml.metadata do
|
270
277
|
xml.name @name
|
271
278
|
xml.time @time.xmlschema
|
272
279
|
xml.bound(
|
273
280
|
minlat: bounds.min_lat,
|
274
281
|
minlon: bounds.min_lon,
|
275
282
|
maxlat: bounds.max_lat,
|
276
|
-
maxlon: bounds.max_lon
|
283
|
+
maxlon: bounds.max_lon
|
277
284
|
)
|
278
|
-
else
|
279
|
-
xml.metadata {
|
280
|
-
xml.name @name
|
281
|
-
xml.time @time.xmlschema
|
282
|
-
xml.bound(
|
283
|
-
minlat: bounds.min_lat,
|
284
|
-
minlon: bounds.min_lon,
|
285
|
-
maxlat: bounds.max_lat,
|
286
|
-
maxlon: bounds.max_lon,
|
287
|
-
)
|
288
|
-
}
|
289
285
|
end
|
286
|
+
end
|
290
287
|
|
288
|
+
unless tracks.nil?
|
291
289
|
tracks.each do |t|
|
292
|
-
xml.trk
|
290
|
+
xml.trk do
|
293
291
|
xml.name t.name
|
294
292
|
|
295
293
|
t.segments.each do |seg|
|
296
|
-
xml.trkseg
|
294
|
+
xml.trkseg do
|
297
295
|
seg.points.each do |p|
|
298
|
-
xml.trkpt(lat: p.lat, lon: p.lon)
|
296
|
+
xml.trkpt(lat: p.lat, lon: p.lon) do
|
299
297
|
xml.time p.time.xmlschema unless p.time.nil?
|
300
298
|
xml.ele p.elevation unless p.elevation.nil?
|
301
299
|
xml << p.extensions.to_xml unless p.extensions.nil?
|
302
|
-
|
300
|
+
end
|
303
301
|
end
|
304
|
-
|
302
|
+
end
|
305
303
|
end
|
306
|
-
|
307
|
-
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
308
307
|
|
308
|
+
unless waypoints.nil?
|
309
309
|
waypoints.each do |w|
|
310
|
-
xml.wpt(lat: w.lat, lon: w.lon)
|
310
|
+
xml.wpt(lat: w.lat, lon: w.lon) do
|
311
311
|
xml.time w.time.xmlschema unless w.time.nil?
|
312
312
|
Waypoint::SUB_ELEMENTS.each do |sub_elem|
|
313
313
|
xml.send(sub_elem, w.send(sub_elem)) if w.respond_to?(sub_elem) && !w.send(sub_elem).nil?
|
314
314
|
end
|
315
|
-
|
316
|
-
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
317
318
|
|
319
|
+
unless routes.nil?
|
318
320
|
routes.each do |r|
|
319
|
-
xml.rte
|
321
|
+
xml.rte do
|
320
322
|
xml.name r.name
|
321
323
|
|
322
324
|
r.points.each do |p|
|
323
|
-
xml.rtept(lat: p.lat, lon: p.lon)
|
325
|
+
xml.rtept(lat: p.lat, lon: p.lon) do
|
324
326
|
xml.time p.time.xmlschema unless p.time.nil?
|
325
327
|
xml.ele p.elevation unless p.elevation.nil?
|
326
|
-
|
328
|
+
end
|
327
329
|
end
|
328
|
-
|
329
|
-
end
|
330
|
-
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
331
334
|
end
|
335
|
+
# rubocop:enable Metrics/BlockLength
|
332
336
|
|
333
|
-
|
337
|
+
doc
|
334
338
|
end
|
335
339
|
|
336
340
|
# Calculates and sets the duration attribute by subtracting the time on
|
337
341
|
# the very first point from the time on the very last point.
|
338
342
|
def calculate_duration
|
339
343
|
@duration = 0
|
340
|
-
if
|
344
|
+
if @tracks.nil? || @tracks.size.zero? || @tracks[0].segments.nil? || @tracks[0].segments.size.zero?
|
341
345
|
return @duration
|
342
346
|
end
|
343
347
|
@duration = (@tracks[-1].segments[-1].points[-1].time - @tracks.first.segments.first.points.first.time)
|
344
|
-
rescue
|
348
|
+
rescue StandardError
|
345
349
|
@duration = 0
|
346
350
|
end
|
347
351
|
end
|