gpx 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|