gpx 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,30 +1,8 @@
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
  # This class will parse the lat/lon and time data from a Magellan track log,
25
3
  # which is a NMEA formatted CSV list of points.
26
4
  class MagellanTrackLog
27
- #PMGNTRK
5
+ # PMGNTRK
28
6
  # This message is to be used to transmit Track information (basically a list of previous position fixes)
29
7
  # which is often displayed on the plotter or map screen of the unit. The first field in this message
30
8
  # is the Latitude, followed by N or S. The next field is the Longitude followed by E or W. The next
@@ -35,98 +13,86 @@ module GPX
35
13
  # of the fix. Note that this field is (and its preceding comma) is only produced by the unit when the
36
14
  # command PMGNCMD,TRACK,2 is given. It is not present when a simple command of PMGNCMD,TRACK is issued.
37
15
 
38
- #NOTE: The Latitude and Longitude Fields are shown as having two decimal
16
+ # NOTE: The Latitude and Longitude Fields are shown as having two decimal
39
17
  # places. As many additional decimal places may be added as long as the total
40
18
  # length of the message does not exceed 82 bytes.
41
19
 
42
20
  # $PMGNTRK,llll.ll,a,yyyyy.yy,a,xxxxx,a,hhmmss.ss,A,c----c,ddmmyy*hh<CR><LF>
43
21
  require 'csv'
44
22
 
45
- LAT = 1
46
- LAT_HEMI = 2
47
- LON = 3
48
- LON_HEMI = 4
49
- ELE = 5
23
+ LAT = 1
24
+ LAT_HEMI = 2
25
+ LON = 3
26
+ LON_HEMI = 4
27
+ ELE = 5
50
28
  ELE_UNITS = 6
51
- TIME = 7
29
+ TIME = 7
52
30
  INVALID_FLAG = 8
53
- DATE = 10
31
+ DATE = 10
54
32
 
55
33
  FEET_TO_METERS = 0.3048
56
34
 
57
35
  class << self
58
-
59
36
  # Takes the name of a magellan file, converts the contents to GPX, and
60
37
  # writes the result to gpx_filename.
61
38
  def convert_to_gpx(magellan_filename, gpx_filename)
62
-
63
39
  segment = Segment.new
64
40
 
65
- CSV.open(magellan_filename, "r").each do |row|
66
- next if(row.size < 10 or row[INVALID_FLAG] == 'V')
41
+ CSV.open(magellan_filename, 'r').each do |row|
42
+ next if (row.size < 10) || (row[INVALID_FLAG] == 'V')
67
43
 
68
- lat_deg = row[LAT][0..1]
69
- lat_min = row[LAT][2...-1]
44
+ lat_deg = row[LAT][0..1]
45
+ lat_min = row[LAT][2...-1]
70
46
  lat_hemi = row[LAT_HEMI]
71
47
 
72
48
  lat = lat_deg.to_f + (lat_min.to_f / 60.0)
73
- lat = (-lat) if(lat_hemi == 'S')
49
+ lat = -lat if lat_hemi == 'S'
74
50
 
75
- lon_deg = row[LON][0..2]
76
- lon_min = row[LON][3..-1]
51
+ lon_deg = row[LON][0..2]
52
+ lon_min = row[LON][3..-1]
77
53
  lon_hemi = row[LON_HEMI]
78
54
 
79
55
  lon = lon_deg.to_f + (lon_min.to_f / 60.0)
80
- lon = (-lon) if(lon_hemi == 'W')
81
-
56
+ lon = -lon if lon_hemi == 'W'
82
57
 
83
58
  ele = row[ELE]
84
59
  ele_units = row[ELE_UNITS]
85
60
  ele = ele.to_f
86
- if(ele_units == 'F')
87
- ele *= FEET_TO_METERS
88
- end
61
+ ele *= FEET_TO_METERS if ele_units == 'F'
89
62
 
90
- hrs = row[TIME][0..1].to_i
63
+ hrs = row[TIME][0..1].to_i
91
64
  mins = row[TIME][2..3].to_i
92
65
  secs = row[TIME][4..5].to_i
93
- day = row[DATE][0..1].to_i
94
- mon = row[DATE][2..3].to_i
95
- yr = 2000 + row[DATE][4..5].to_i
66
+ day = row[DATE][0..1].to_i
67
+ mon = row[DATE][2..3].to_i
68
+ yr = 2000 + row[DATE][4..5].to_i
96
69
 
97
70
  time = Time.gm(yr, mon, day, hrs, mins, secs)
98
71
 
99
- #must create point
100
- pt = TrackPoint.new(:lat => lat, :lon => lon, :time => time, :elevation => ele)
72
+ # must create point
73
+ pt = TrackPoint.new(lat: lat, lon: lon, time: time, elevation: ele)
101
74
  segment.append_point(pt)
102
-
103
75
  end
104
76
 
105
77
  trk = Track.new
106
78
  trk.append_segment(segment)
107
- gpx_file = GPXFile.new(:tracks => [trk])
79
+ gpx_file = GPXFile.new(tracks: [trk])
108
80
  gpx_file.write(gpx_filename)
109
-
110
81
  end
111
82
 
112
83
  # Tests to see if the given file is a magellan NMEA track log.
113
- def is_magellan_file?(filename)
84
+ def magellan_file?(filename)
114
85
  i = 0
115
- File.open(filename, "r") do |f|
86
+ File.open(filename, 'r') do |f|
116
87
  f.each do |line|
117
- i += 1
118
- if line =~ /^\$PMGNTRK/
119
- return true
120
- elsif line =~ /<\?xml/
121
- return false
122
- elsif(i > 10)
123
- return false
124
- end
88
+ i += 1
89
+ return true if line =~ /^\$PMGNTRK/
90
+ return false if line =~ /<\?xml/
91
+ return false if i > 10
125
92
  end
126
93
  end
127
- return false
94
+ false
128
95
  end
129
96
  end
130
-
131
97
  end
132
98
  end
@@ -1,46 +1,31 @@
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
  # The base class for all points. Trackpoint and Waypoint both descend from this base class.
25
3
  class Point < Base
26
- D_TO_R = Math::PI/180.0;
27
- attr_accessor :lat, :lon, :time, :elevation, :gpx_file, :speed, :extensions
4
+ D_TO_R = Math::PI / 180.0
5
+ attr_accessor :time, :elevation, :gpx_file, :speed, :extensions
6
+ attr_reader :lat, :lon
28
7
 
29
8
  # When you need to manipulate individual points, you can create a Point
30
9
  # object with a latitude, a longitude, an elevation, and a time. In
31
10
  # addition, you can pass an XML element to this initializer, and the
32
11
  # relevant info will be parsed out.
33
- def initialize(opts = {:lat => 0.0, :lon => 0.0, :elevation => 0.0, :time => Time.now } )
12
+ def initialize(opts = { lat: 0.0, lon: 0.0, elevation: 0.0, time: Time.now })
34
13
  @gpx_file = opts[:gpx_file]
35
- if (opts[:element])
14
+ if opts[:element]
36
15
  elem = opts[:element]
37
- @lat, @lon = elem["lat"].to_f, elem["lon"].to_f
38
- @latr, @lonr = (D_TO_R * @lat), (D_TO_R * @lon)
39
- #'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
40
- @time = (Time.xmlschema(elem.at("time").inner_text) rescue nil)
41
- @elevation = elem.at("ele").inner_text.to_f unless elem.at("ele").nil?
42
- @speed = elem.at("speed").inner_text.to_f unless elem.at("speed").nil?
43
- @extensions = elem.at("extensions") unless elem.at("extensions").nil?
16
+ @lat = elem['lat'].to_f
17
+ @lon = elem['lon'].to_f
18
+ @latr = (D_TO_R * @lat)
19
+ @lonr = (D_TO_R * @lon)
20
+ # '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
21
+ @time = (begin
22
+ Time.xmlschema(elem.at('time').inner_text)
23
+ rescue StandardError
24
+ nil
25
+ end)
26
+ @elevation = elem.at('ele').inner_text.to_f unless elem.at('ele').nil?
27
+ @speed = elem.at('speed').inner_text.to_f unless elem.at('speed').nil?
28
+ @extensions = elem.at('extensions') unless elem.at('extensions').nil?
44
29
  else
45
30
  @lat = opts[:lat]
46
31
  @lon = opts[:lon]
@@ -49,10 +34,8 @@ module GPX
49
34
  @speed = opts[:speed]
50
35
  @extensions = opts[:extensions]
51
36
  end
52
-
53
37
  end
54
38
 
55
-
56
39
  # Returns the latitude and longitude (in that order), separated by the
57
40
  # given delimeter. This is useful for passing a point into another API
58
41
  # (i.e. the Google Maps javascript API).
@@ -1,58 +1,34 @@
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 Route in GPX is very similar to a Track, but it is created by a user
25
3
  # from a series of Waypoints, whereas a Track is created by the GPS device
26
4
  # automatically logging your progress at regular intervals.
27
5
  class Route < Base
28
-
29
6
  attr_accessor :points, :name, :gpx_file
30
7
 
31
8
  # Initialize a Route from a XML::Node.
32
9
  def initialize(opts = {})
33
- if(opts[:gpx_file] and opts[:element])
10
+ if opts[:gpx_file] && opts[:element]
34
11
  rte_element = opts[:element]
35
12
  @gpx_file = opts[:gpx_file]
36
- @name = rte_element.at("name").inner_text
13
+ @name = rte_element.at('name').inner_text
37
14
  @points = []
38
- rte_element.search("rtept").each do |point|
39
- @points << Point.new(:element => point, :gpx_file => @gpx_file)
15
+ rte_element.search('rtept').each do |point|
16
+ @points << Point.new(element: point, gpx_file: @gpx_file)
40
17
  end
41
18
  else
42
- @points = (opts[:points] or [])
19
+ @points = (opts[:points] || [])
43
20
  @name = (opts[:name])
44
21
  end
45
-
46
22
  end
47
23
 
48
24
  # Delete points outside of a given area.
49
25
  def crop(area)
50
- points.delete_if{ |pt| not area.contains? pt }
26
+ points.delete_if { |pt| !area.contains? pt }
51
27
  end
52
28
 
53
29
  # Delete points within the given area.
54
30
  def delete_area(area)
55
- points.delete_if{ |pt| area.contains? pt }
31
+ points.delete_if { |pt| area.contains? pt }
56
32
  end
57
33
  end
58
34
  end
@@ -1,32 +1,9 @@
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 segment is the basic container in a GPX file. A Segment contains points
25
3
  # (in this lib, they're called TrackPoints). A Track contains Segments. An
26
4
  # instance of Segment knows its highest point, lowest point, earliest and
27
5
  # latest points, distance, and bounds.
28
6
  class Segment < Base
29
-
30
7
  attr_reader :earliest_point, :latest_point, :bounds, :highest_point, :lowest_point, :distance, :duration
31
8
  attr_accessor :points, :track
32
9
 
@@ -43,15 +20,12 @@ module GPX
43
20
  @distance = 0.0
44
21
  @duration = 0.0
45
22
  @bounds = Bounds.new
46
- if(opts[:element])
47
- segment_element = opts[:element]
48
- last_pt = nil
49
- if segment_element.is_a?(Nokogiri::XML::Node)
50
- segment_element.search("trkpt").each do |trkpt|
51
- pt = TrackPoint.new(:element => trkpt, :segment => self, :gpx_file => @gpx_file)
52
- append_point(pt)
53
- end
54
- end
23
+
24
+ segment_element = opts[:element]
25
+ return unless segment_element && segment_element.is_a?(Nokogiri::XML::Node)
26
+ segment_element.search('trkpt').each do |trkpt|
27
+ pt = TrackPoint.new(element: trkpt, segment: self, gpx_file: @gpx_file)
28
+ append_point(pt)
55
29
  end
56
30
  end
57
31
 
@@ -59,8 +33,8 @@ module GPX
59
33
  def append_point(pt)
60
34
  last_pt = @points[-1]
61
35
  if pt.time
62
- @earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
63
- @latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)
36
+ @earliest_point = pt if @earliest_point.nil? || (pt.time < @earliest_point.time)
37
+ @latest_point = pt if @latest_point.nil? || (pt.time > @latest_point.time)
64
38
  else
65
39
  # when no time information in data, we consider the points are ordered
66
40
  @earliest_point = @points[0]
@@ -68,8 +42,8 @@ module GPX
68
42
  end
69
43
 
70
44
  if pt.elevation
71
- @lowest_point = pt if(@lowest_point.nil? or pt.elevation < @lowest_point.elevation)
72
- @highest_point = pt if(@highest_point.nil? or pt.elevation > @highest_point.elevation)
45
+ @lowest_point = pt if @lowest_point.nil? || (pt.elevation < @lowest_point.elevation)
46
+ @highest_point = pt if @highest_point.nil? || (pt.elevation > @highest_point.elevation)
73
47
  end
74
48
  @bounds.min_lat = pt.lat if pt.lat < @bounds.min_lat
75
49
  @bounds.min_lon = pt.lon if pt.lon < @bounds.min_lon
@@ -77,14 +51,16 @@ module GPX
77
51
  @bounds.max_lon = pt.lon if pt.lon > @bounds.max_lon
78
52
  if last_pt
79
53
  @distance += haversine_distance(last_pt, pt)
80
- @duration += pt.time - last_pt.time if pt.time and last_pt.time
54
+ @duration += pt.time - last_pt.time if pt.time && last_pt.time
81
55
  end
82
56
  @points << pt
83
57
  end
84
58
 
85
59
  # Returns true if the given time is within this Segment.
86
60
  def contains_time?(time)
87
- (time >= @earliest_point.time and time <= @latest_point.time) rescue false
61
+ ((time >= @earliest_point.time) && (time <= @latest_point.time))
62
+ rescue StandardError
63
+ false
88
64
  end
89
65
 
90
66
  # Finds the closest point in time to the passed-in time argument. Useful
@@ -97,12 +73,12 @@ module GPX
97
73
  # Deletes all points within this Segment that lie outside of the given
98
74
  # area (which should be a Bounds object).
99
75
  def crop(area)
100
- delete_if { |pt| not area.contains?(pt) }
76
+ delete_if { |pt| !area.contains?(pt) }
101
77
  end
102
78
 
103
79
  # Deletes all points in this Segment that lie within the given area.
104
80
  def delete_area(area)
105
- delete_if{ |pt| area.contains?(pt) }
81
+ delete_if { |pt| area.contains?(pt) }
106
82
  end
107
83
 
108
84
  # A handy method that deletes points based on a block that is passed in.
@@ -114,18 +90,17 @@ module GPX
114
90
  keep_points = []
115
91
  last_pt = nil
116
92
  points.each do |pt|
117
- unless yield(pt)
118
- keep_points << pt
119
- update_meta_data(pt, last_pt)
120
- last_pt = pt
121
- end
93
+ next if yield(pt)
94
+ keep_points << pt
95
+ update_meta_data(pt, last_pt)
96
+ last_pt = pt
122
97
  end
123
98
  @points = keep_points
124
99
  end
125
100
 
126
101
  # Returns true if this Segment has no points.
127
102
  def empty?
128
- (points.nil? or (points.size == 0))
103
+ (points.nil? || points.empty?)
129
104
  end
130
105
 
131
106
  # Prints out a nice summary of this Segment.
@@ -133,31 +108,31 @@ module GPX
133
108
  result = "Track Segment\n"
134
109
  result << "\tSize: #{points.size} points\n"
135
110
  result << "\tDistance: #{distance} km\n"
136
- result << "\tEarliest Point: #{earliest_point.time.to_s} \n"
137
- result << "\tLatest Point: #{latest_point.time.to_s} \n"
111
+ result << "\tEarliest Point: #{earliest_point.time} \n"
112
+ result << "\tLatest Point: #{latest_point.time} \n"
138
113
  result << "\tLowest Point: #{lowest_point.elevation} \n"
139
114
  result << "\tHighest Point: #{highest_point.elevation}\n "
140
- result << "\tBounds: #{bounds.to_s}"
115
+ result << "\tBounds: #{bounds}"
141
116
  result
142
117
  end
143
118
 
144
119
  def find_point_by_time_or_offset(indicator)
145
120
  if indicator.nil?
146
- return nil
121
+ nil
147
122
  elsif indicator.is_a?(Integer)
148
- return closest_point(@earliest_point.time + indicator)
149
- elsif(indicator.is_a?(Time))
150
- return closest_point(indicator)
123
+ closest_point(@earliest_point.time + indicator)
124
+ elsif indicator.is_a?(Time)
125
+ closest_point(indicator)
151
126
  else
152
- raise Exception, "find_end_point_by_time_or_offset requires an argument of type Time or Integer"
127
+ raise Exception, 'find_end_point_by_time_or_offset requires an argument of type Time or Integer'
153
128
  end
154
129
  end
155
-
130
+
156
131
  # 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.
157
- def smooth_location_by_average(opts={})
132
+ def smooth_location_by_average(opts = {})
158
133
  seconds_either_side = opts[:averaging_window] || 20
159
134
 
160
- #calculate the first and last points to which the smoothing should be applied
135
+ # calculate the first and last points to which the smoothing should be applied
161
136
  earliest = (find_point_by_time_or_offset(opts[:start]) || @earliest_point).time
162
137
  latest = (find_point_by_time_or_offset(opts[:end]) || @latest_point).time
163
138
 
@@ -165,18 +140,18 @@ module GPX
165
140
 
166
141
  @points.each do |point|
167
142
  if point.time > latest || point.time < earliest
168
- tmp_points.push point #add the point unaltered
169
- next
143
+ tmp_points.push point # add the point unaltered
144
+ next
170
145
  end
171
146
  lat_av = 0.to_f
172
147
  lon_av = 0.to_f
173
148
  alt_av = 0.to_f
174
149
  n = 0
175
- # k ranges from the time of the current point +/- 20s
176
- (-1*seconds_either_side..seconds_either_side).each do |k|
150
+ # k ranges from the time of the current point +/- 20s
151
+ (-1 * seconds_either_side..seconds_either_side).each do |k|
177
152
  # find the point nearest to the time offset indicated by k
178
153
  contributing_point = closest_point(point.time + k)
179
- #sum up the contributions to the average
154
+ # sum up the contributions to the average
180
155
  lat_av += contributing_point.lat
181
156
  lon_av += contributing_point.lon
182
157
  alt_av += contributing_point.elevation
@@ -184,39 +159,39 @@ module GPX
184
159
  end
185
160
  # calculate the averages
186
161
  tmp_point = point.clone
187
- tmp_point.lon = ((lon_av) / n).round(7)
188
- tmp_point.elevation = ((alt_av) / n).round(2)
189
- tmp_point.lat = ((lat_av) / n).round(7)
162
+ tmp_point.lon = (lon_av / n).round(7)
163
+ tmp_point.elevation = (alt_av / n).round(2)
164
+ tmp_point.lat = (lat_av / n).round(7)
190
165
  tmp_points.push tmp_point
191
166
  end
192
- last_pt = nil
193
167
  @points.clear
194
168
  reset_meta_data
195
- #now commit the averages back and recalculate the distances
169
+ # now commit the averages back and recalculate the distances
196
170
  tmp_points.each do |point|
197
171
  append_point(point)
198
172
  end
199
173
  end
200
174
 
201
175
  protected
176
+
177
+ # rubocop:disable Style/GuardClause
202
178
  def find_closest(pts, time)
203
179
  return pts.first if pts.size == 1
204
- midpoint = pts.size/2
180
+ midpoint = pts.size / 2
205
181
  if pts.size == 2
206
182
  diff_1 = pts[0].time - time
207
183
  diff_2 = pts[1].time - time
208
184
  return (diff_1 < diff_2 ? pts[0] : pts[1])
209
185
  end
210
- if time >= pts[midpoint].time and time <= pts[midpoint+1].time
211
-
186
+ if (time >= pts[midpoint].time) && (time <= pts[midpoint + 1].time)
212
187
  return pts[midpoint]
213
-
214
- elsif(time <= pts[midpoint].time)
188
+ elsif time <= pts[midpoint].time
215
189
  return find_closest(pts[0..midpoint], time)
216
190
  else
217
- return find_closest(pts[(midpoint+1)..-1], time)
191
+ return find_closest(pts[(midpoint + 1)..-1], time)
218
192
  end
219
193
  end
194
+ # rubocop:enable Style/GuardClause
220
195
 
221
196
  # Calculate the Haversine distance between two points. This is the method
222
197
  # the library uses to calculate the cumulative distance of GPX files.
@@ -224,11 +199,6 @@ module GPX
224
199
  p1.haversine_distance_from(p2)
225
200
  end
226
201
 
227
- # Calculate the plain Pythagorean difference between two points. Not currently used.
228
- def pythagorean_distance(p1, p2)
229
- p1.pythagorean_distance_from(p2)
230
- end
231
-
232
202
  # Calculates the distance between two points using the Law of Cosines formula. Not currently used.
233
203
  def law_of_cosines_distance(p1, p2)
234
204
  p1.law_of_cosines_distance_from(p2)
@@ -246,8 +216,8 @@ module GPX
246
216
 
247
217
  def update_meta_data(pt, last_pt)
248
218
  if pt.time
249
- @earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
250
- @latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)
219
+ @earliest_point = pt if @earliest_point.nil? || (pt.time < @earliest_point.time)
220
+ @latest_point = pt if @latest_point.nil? || (pt.time > @latest_point.time)
251
221
  else
252
222
  # when no time information in data, we consider the points are ordered
253
223
  @earliest_point = @points[0]
@@ -255,16 +225,14 @@ module GPX
255
225
  end
256
226
 
257
227
  if pt.elevation
258
- @lowest_point = pt if(@lowest_point.nil? or pt.elevation < @lowest_point.elevation)
259
- @highest_point = pt if(@highest_point.nil? or pt.elevation > @highest_point.elevation)
228
+ @lowest_point = pt if @lowest_point.nil? || (pt.elevation < @lowest_point.elevation)
229
+ @highest_point = pt if @highest_point.nil? || (pt.elevation > @highest_point.elevation)
260
230
  end
261
231
  @bounds.add(pt)
262
- if last_pt
263
- @distance += haversine_distance(last_pt, pt)
264
- @duration += pt.time - last_pt.time if pt.time and last_pt.time
265
- end
266
- end
267
232
 
233
+ return unless last_pt
234
+ @distance += haversine_distance(last_pt, pt)
235
+ @duration += pt.time - last_pt.time if pt.time && last_pt.time
236
+ end
268
237
  end
269
-
270
238
  end