gpx 0.9.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +36 -0
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +162 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +6 -5
  7. data/CHANGELOG.md +15 -0
  8. data/Gemfile +2 -0
  9. data/LICENSE.txt +1 -1
  10. data/README.md +20 -5
  11. data/Rakefile +22 -12
  12. data/bin/gpx_distance +5 -6
  13. data/bin/gpx_smooth +25 -26
  14. data/gpx.gemspec +13 -12
  15. data/lib/gpx/bounds.rb +13 -31
  16. data/lib/gpx/geo_json.rb +199 -0
  17. data/lib/gpx/gpx.rb +4 -26
  18. data/lib/gpx/gpx_file.rb +140 -134
  19. data/lib/gpx/magellan_track_log.rb +34 -66
  20. data/lib/gpx/point.rb +22 -35
  21. data/lib/gpx/route.rb +10 -31
  22. data/lib/gpx/segment.rb +63 -90
  23. data/lib/gpx/track.rb +38 -42
  24. data/lib/gpx/track_point.rb +32 -0
  25. data/lib/gpx/version.rb +3 -1
  26. data/lib/gpx/waypoint.rb +10 -34
  27. data/lib/gpx.rb +13 -34
  28. data/tests/geojson_files/combined_data.json +68 -0
  29. data/tests/geojson_files/line_string_data.json +83 -0
  30. data/tests/geojson_files/multi_line_string_data.json +74 -0
  31. data/tests/geojson_files/multi_point_data.json +14 -0
  32. data/tests/geojson_files/point_data.json +22 -0
  33. data/tests/geojson_test.rb +92 -0
  34. data/tests/gpx10_test.rb +7 -6
  35. data/tests/gpx_file_test.rb +31 -19
  36. data/tests/gpx_files/one_segment_mixed_times.gpx +884 -0
  37. data/tests/gpx_files/routes_without_names.gpx +29 -0
  38. data/tests/gpx_files/with_empty_tracks.gpx +72 -0
  39. data/tests/magellan_test.rb +12 -11
  40. data/tests/output_test.rb +93 -94
  41. data/tests/route_test.rb +75 -30
  42. data/tests/segment_test.rb +104 -93
  43. data/tests/track_file_test.rb +50 -70
  44. data/tests/track_point_test.rb +22 -11
  45. data/tests/track_test.rb +73 -61
  46. data/tests/waypoint_test.rb +46 -48
  47. metadata +47 -18
  48. data/lib/gpx/trackpoint.rb +0 -60
data/lib/gpx/track.rb CHANGED
@@ -1,25 +1,5 @@
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
- #++
1
+ # frozen_string_literal: true
2
+
23
3
  module GPX
24
4
  # In GPX, a single Track can hold multiple Segments, each of which hold
25
5
  # multiple points (in this library, those points are instances of
@@ -34,28 +14,45 @@ module GPX
34
14
  # Initialize a track from a XML::Node, or, if no :element option is
35
15
  # passed, initialize a blank Track object.
36
16
  def initialize(opts = {})
17
+ super()
37
18
  @gpx_file = opts[:gpx_file]
38
19
  @segments = []
39
20
  @points = []
40
21
  reset_meta_data
41
- if(opts[:element])
42
- trk_element = opts[:element]
43
- @name = (trk_element.at("name").inner_text rescue "")
44
- @comment = (trk_element.at('cmt').inner_text rescue '')
45
- @description = (trk_element.at('desc').inner_text rescue '')
46
- trk_element.search("trkseg").each do |seg_element|
47
- seg = Segment.new(:element => seg_element, :track => self, :gpx_file => @gpx_file)
48
- update_meta_data(seg)
49
- @segments << seg
50
- end
22
+
23
+ return unless opts[:element]
24
+
25
+ trk_element = opts[:element]
26
+ @name = (
27
+ begin
28
+ trk_element.at('name').inner_text
29
+ rescue StandardError
30
+ ''
31
+ end)
32
+ @comment = (
33
+ begin
34
+ trk_element.at('cmt').inner_text
35
+ rescue StandardError
36
+ ''
37
+ end)
38
+ @description = (
39
+ begin
40
+ trk_element.at('desc').inner_text
41
+ rescue StandardError
42
+ ''
43
+ end)
44
+ trk_element.search('trkseg').each do |seg_element|
45
+ seg = Segment.new(element: seg_element, track: self, gpx_file: @gpx_file)
46
+ append_segment(seg)
51
47
  end
52
48
  end
53
49
 
54
50
  # Append a segment to this track, updating its meta data along the way.
55
51
  def append_segment(seg)
52
+ return if seg.points.empty?
53
+
56
54
  update_meta_data(seg)
57
55
  @segments << seg
58
- @points.concat(seg.points) unless seg.nil?
59
56
  end
60
57
 
61
58
  # Returns true if the given time occurs within any of the segments of this track.
@@ -63,7 +60,7 @@ module GPX
63
60
  segments.each do |seg|
64
61
  return true if seg.contains_time?(time)
65
62
  end
66
- return false
63
+ false
67
64
  end
68
65
 
69
66
  # Finds the closest point (to "time") within this track. Useful for
@@ -82,7 +79,7 @@ module GPX
82
79
  seg.crop(area)
83
80
  update_meta_data(seg) unless seg.empty?
84
81
  end
85
- segments.delete_if { |seg| seg.empty? }
82
+ segments.delete_if(&:empty?)
86
83
  end
87
84
 
88
85
  # Deletes all points within a given area and updates the meta data.
@@ -92,13 +89,13 @@ module GPX
92
89
  seg.delete_area(area)
93
90
  update_meta_data(seg) unless seg.empty?
94
91
  end
95
- segments.delete_if { |seg| seg.empty? }
92
+ segments.delete_if(&:empty?)
96
93
  end
97
94
 
98
95
  # Returns true if this track has no points in it. This should return
99
96
  # true even when the track has empty segments.
100
97
  def empty?
101
- (points.nil? or points.size.zero?)
98
+ (points.nil? || points.empty?)
102
99
  end
103
100
 
104
101
  # Prints out a friendly summary of this track (sans points). Useful for
@@ -115,7 +112,7 @@ module GPX
115
112
  result << "\tMoving duration: #{moving_duration} km\n"
116
113
  result << "\tLowest Point: #{lowest_point.elevation} \n"
117
114
  result << "\tHighest Point: #{highest_point.elevation}\n "
118
- result << "\tBounds: #{bounds.to_s}"
115
+ result << "\tBounds: #{bounds}"
119
116
  result
120
117
  end
121
118
 
@@ -125,12 +122,12 @@ module GPX
125
122
  @distance += seg.distance
126
123
  end
127
124
  end
128
-
125
+
129
126
  protected
130
127
 
131
128
  def update_meta_data(seg)
132
- @lowest_point = seg.lowest_point if(@lowest_point.nil? or seg.lowest_point.elevation < @lowest_point.elevation)
133
- @highest_point = seg.highest_point if(@highest_point.nil? or seg.highest_point.elevation > @highest_point.elevation)
129
+ @lowest_point = seg.lowest_point if @lowest_point.nil? || (seg.lowest_point.elevation < @lowest_point.elevation)
130
+ @highest_point = seg.highest_point if @highest_point.nil? || (seg.highest_point.elevation > @highest_point.elevation)
134
131
  @bounds.add(seg.bounds)
135
132
  @distance += seg.distance
136
133
  @moving_duration += seg.duration
@@ -145,6 +142,5 @@ module GPX
145
142
  @moving_duration = 0.0
146
143
  @points = []
147
144
  end
148
-
149
145
  end
150
146
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GPX
4
+ # Basically the same as a point, the TrackPoint class is supposed to
5
+ # represent the points that are children of Segment elements. So, the only
6
+ # real difference is that TrackPoints hold a reference to their parent
7
+ # Segments.
8
+ class TrackPoint < Point
9
+ RADIUS = 6371 # earth's mean radius in km
10
+
11
+ attr_accessor :segment
12
+
13
+ def initialize(opts = {})
14
+ super(opts)
15
+ @segment = opts[:segment]
16
+ end
17
+
18
+ # Units are in km
19
+ def haversine_distance_from(p2)
20
+ d_lat = p2.latr - latr
21
+ d_lon = p2.lonr - lonr
22
+ a = Math.sin(d_lat / 2) * Math.sin(d_lat / 2) + Math.cos(latr) * Math.cos(p2.latr) * Math.sin(d_lon / 2) * Math.sin(d_lon / 2)
23
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
24
+ RADIUS * c
25
+ end
26
+
27
+ # Units are in km
28
+ def law_of_cosines_distance_from(p2)
29
+ Math.acos(Math.sin(latr) * Math.sin(p2.latr) + Math.cos(latr) * Math.cos(p2.latr) * Math.cos(p2.lonr - lonr)) * RADIUS
30
+ end
31
+ end
32
+ end
data/lib/gpx/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GPX
2
- VERSION = "0.9.0"
4
+ VERSION = "1.1.0"
3
5
  end
data/lib/gpx/waypoint.rb CHANGED
@@ -1,56 +1,32 @@
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
- #++
1
+ # frozen_string_literal: true
2
+
23
3
  module GPX
24
4
  # This class supports the concept of a waypoint. Beware that this class has
25
5
  # not seen much use yet, since WalkingBoss does not use waypoints right now.
26
6
  class Waypoint < Point
27
-
28
- SUB_ELEMENTS = %w{ele magvar geoidheight name cmt desc src link sym type fix sat hdop vdop pdop ageofdgpsdata dgpsid extensions}
7
+ SUB_ELEMENTS = %w[ele magvar geoidheight name cmt desc src link sym type fix sat hdop vdop pdop ageofdgpsdata dgpsid extensions].freeze
29
8
 
30
9
  attr_reader :gpx_file
10
+
31
11
  SUB_ELEMENTS.each { |sub_el| attr_accessor sub_el.to_sym }
32
12
 
33
13
  # Not implemented
34
- def crop(area)
35
- end
14
+ def crop(area); end
36
15
 
37
16
  # Not implemented
38
- def delete_area(area)
39
- end
17
+ def delete_area(area); end
40
18
 
41
19
  # Initializes a waypoint from a XML::Node.
42
20
  def initialize(opts = {})
43
- if(opts[:element] and opts[:gpx_file])
21
+ if opts[:element] && opts[:gpx_file]
44
22
  wpt_elem = opts[:element]
45
23
  @gpx_file = opts[:gpx_file]
46
- super(:element => wpt_elem, :gpx_file => @gpx_file)
24
+ super(element: wpt_elem, gpx_file: @gpx_file)
47
25
  instantiate_with_text_elements(wpt_elem, SUB_ELEMENTS)
48
26
  else
49
27
  opts.each do |key, value|
50
28
  assignment_method = "#{key}="
51
- if self.respond_to?(assignment_method)
52
- self.send(assignment_method, value)
53
- end
29
+ send(assignment_method, value) if respond_to?(assignment_method)
54
30
  end
55
31
  end
56
32
  end
@@ -65,7 +41,7 @@ module GPX
65
41
  result << "\tElevation: #{elevation}\n "
66
42
  result << "\tTime: #{time}\n"
67
43
  SUB_ELEMENTS.each do |sub_element_attribute|
68
- val = self.send(sub_element_attribute)
44
+ val = send(sub_element_attribute)
69
45
  result << "\t#{sub_element_attribute}: #{val}\n" unless val.nil?
70
46
  end
71
47
  result
data/lib/gpx.rb CHANGED
@@ -1,38 +1,17 @@
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
- #++
1
+ # frozen_string_literal: true
23
2
 
24
3
  require 'time'
25
4
  require 'nokogiri'
26
5
 
27
- require File.expand_path('../gpx/version', __FILE__)
28
-
29
- require File.expand_path('../gpx/gpx', __FILE__)
30
- require File.expand_path('../gpx/gpx_file', __FILE__)
31
- require File.expand_path('../gpx/bounds', __FILE__)
32
- require File.expand_path('../gpx/track', __FILE__)
33
- require File.expand_path('../gpx/route', __FILE__)
34
- require File.expand_path('../gpx/segment', __FILE__)
35
- require File.expand_path('../gpx/point', __FILE__)
36
- require File.expand_path('../gpx/trackpoint', __FILE__)
37
- require File.expand_path('../gpx/waypoint', __FILE__)
38
- require File.expand_path('../gpx/magellan_track_log', __FILE__)
6
+ require File.expand_path('gpx/version', __dir__)
7
+ require File.expand_path('gpx/gpx', __dir__)
8
+ require File.expand_path('gpx/gpx_file', __dir__)
9
+ require File.expand_path('gpx/bounds', __dir__)
10
+ require File.expand_path('gpx/track', __dir__)
11
+ require File.expand_path('gpx/route', __dir__)
12
+ require File.expand_path('gpx/segment', __dir__)
13
+ require File.expand_path('gpx/point', __dir__)
14
+ require File.expand_path('gpx/track_point', __dir__)
15
+ require File.expand_path('gpx/waypoint', __dir__)
16
+ require File.expand_path('gpx/magellan_track_log', __dir__)
17
+ require File.expand_path('gpx/geo_json', __dir__)
@@ -0,0 +1,68 @@
1
+ {
2
+ "type": "FeatureCollection",
3
+ "features": [{
4
+ "type": "Feature",
5
+ "geometry": {
6
+ "type": "LineString",
7
+ "coordinates": [
8
+ [-118.41511, 34.06298, 80],
9
+ [-118.41506, 34.06301, 80],
10
+ [-118.415, 34.06305, 80],
11
+ [-118.41494, 34.06309, 80]
12
+ ]
13
+ }
14
+ }, {
15
+ "type": "Feature",
16
+ "geometry": {
17
+ "type": "LineString",
18
+ "coordinates": [
19
+ [-118.3689, 34.05826, 40],
20
+ [-118.36894, 34.05818, 40],
21
+ [-118.369, 34.05806, 40]
22
+ ]
23
+ }
24
+ }, {
25
+ "type": "Feature",
26
+ "geometry": {
27
+ "type": "LineString",
28
+ "coordinates": [
29
+ [-118.35042, 34.03788, 30],
30
+ [-118.35046, 34.03779, 30]
31
+ ]
32
+ }
33
+ }, {
34
+ "type": "Feature",
35
+ "geometry": {
36
+ "type": "MultiLineString",
37
+ "coordinates": [
38
+ [
39
+ [-118.41511, 34.06298, 80],
40
+ [-118.41506, 34.06301, 80],
41
+ [-118.415, 34.06305, 80],
42
+ [-118.41494, 34.06309, 80]
43
+ ],
44
+ [
45
+ [-118.3689, 34.05826, 40],
46
+ [-118.36894, 34.05818, 40],
47
+ [-118.369, 34.05806, 40]
48
+ ]
49
+ ]
50
+ }
51
+ }, {
52
+ "type": "Feature",
53
+ "geometry": {
54
+ "type": "Point",
55
+ "coordinates": [-118.41585, 34.06253, 80]
56
+ }
57
+ }, {
58
+ "type": "Feature",
59
+ "geometry": {
60
+ "type": "MultiPoint",
61
+ "coordinates": [
62
+ [-118.41585, 34.06253, 80],
63
+ [-118.4158, 34.06256, 80],
64
+ [-118.41575, 34.06259, 80]
65
+ ]
66
+ }
67
+ }]
68
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "type": "FeatureCollection",
3
+ "features": [{
4
+ "type": "Feature",
5
+ "geometry": {
6
+ "type": "LineString",
7
+ "coordinates": [
8
+ [-118.41585, 34.06253, 80],
9
+ [-118.4158, 34.06256, 80],
10
+ [-118.41575, 34.06259, 80],
11
+ [-118.4157, 34.06262, 80],
12
+ [-118.41566, 34.06265, 80],
13
+ [-118.41561, 34.06268, 80],
14
+ [-118.41556, 34.06271, 80],
15
+ [-118.41551, 34.06274, 80],
16
+ [-118.41546, 34.06277, 80],
17
+ [-118.41541, 34.0628, 80],
18
+ [-118.41536, 34.06283, 80],
19
+ [-118.41531, 34.06286, 80],
20
+ [-118.41526, 34.06289, 80],
21
+ [-118.41521, 34.06292, 80],
22
+ [-118.41516, 34.06295, 80],
23
+ [-118.41511, 34.06298, 80],
24
+ [-118.41506, 34.06301, 80],
25
+ [-118.415, 34.06305, 80],
26
+ [-118.41494, 34.06309, 80]
27
+ ]
28
+ }
29
+ }, {
30
+ "type": "Feature",
31
+ "geometry": {
32
+ "type": "LineString",
33
+ "coordinates": [
34
+ [-118.36855, 34.05844, 40],
35
+ [-118.36849, 34.05843, 40],
36
+ [-118.36843, 34.05842, 40],
37
+ [-118.36837, 34.05841, 40],
38
+ [-118.36906, 34.05878, 40],
39
+ [-118.36895, 34.05877, 40],
40
+ [-118.36884, 34.05876, 40],
41
+ [-118.36873, 34.05875, 40],
42
+ [-118.36866, 34.05874, 40],
43
+ [-118.3687, 34.05866, 40],
44
+ [-118.36874, 34.05858, 40],
45
+ [-118.36878, 34.0585, 40],
46
+ [-118.36882, 34.05842, 40],
47
+ [-118.36886, 34.05834, 40],
48
+ [-118.3689, 34.05826, 40],
49
+ [-118.36894, 34.05818, 40],
50
+ [-118.369, 34.05806, 40]
51
+ ]
52
+ }
53
+ }, {
54
+ "type": "Feature",
55
+ "geometry": {
56
+ "type": "LineString",
57
+ "coordinates": [
58
+ [-118.35043, 34.0392, 30],
59
+ [-118.35047, 34.03911, 30],
60
+ [-118.35051, 34.03902, 30],
61
+ [-118.35055, 34.03893, 30],
62
+ [-118.35057, 34.03887, 30],
63
+ [-118.35045, 34.03885, 30],
64
+ [-118.35033, 34.03883, 30],
65
+ [-118.35021, 34.03881, 30],
66
+ [-118.35009, 34.03879, 30],
67
+ [-118.35002, 34.03878, 30],
68
+ [-118.35006, 34.03869, 30],
69
+ [-118.3501, 34.0386, 30],
70
+ [-118.35014, 34.03851, 30],
71
+ [-118.35018, 34.03842, 30],
72
+ [-118.35022, 34.03833, 30],
73
+ [-118.35026, 34.03824, 30],
74
+ [-118.3503, 34.03815, 30],
75
+ [-118.35034, 34.03806, 30],
76
+ [-118.35038, 34.03797, 30],
77
+ [-118.35042, 34.03788, 30],
78
+ [-118.35046, 34.03779, 30],
79
+ [-118.3505, 34.03768, 30]
80
+ ]
81
+ }
82
+ }]
83
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "type": "FeatureCollection",
3
+ "features": [{
4
+ "type": "Feature",
5
+ "geometry": {
6
+ "type": "MultiLineString",
7
+ "coordinates": [
8
+ [
9
+ [-118.41585, 34.06253, 80],
10
+ [-118.4158, 34.06256, 80],
11
+ [-118.41575, 34.06259, 80],
12
+ [-118.4157, 34.06262, 80],
13
+ [-118.41566, 34.06265, 80],
14
+ [-118.41561, 34.06268, 80],
15
+ [-118.41556, 34.06271, 80],
16
+ [-118.41551, 34.06274, 80],
17
+ [-118.41546, 34.06277, 80],
18
+ [-118.41541, 34.0628, 80],
19
+ [-118.41536, 34.06283, 80],
20
+ [-118.41531, 34.06286, 80],
21
+ [-118.41526, 34.06289, 80],
22
+ [-118.41521, 34.06292, 80],
23
+ [-118.41516, 34.06295, 80],
24
+ [-118.41511, 34.06298, 80],
25
+ [-118.41506, 34.06301, 80],
26
+ [-118.415, 34.06305, 80],
27
+ [-118.41494, 34.06309, 80]
28
+ ],
29
+ [
30
+ [-118.36855, 34.05844, 40],
31
+ [-118.36849, 34.05843, 40],
32
+ [-118.36843, 34.05842, 40],
33
+ [-118.36837, 34.05841, 40],
34
+ [-118.36906, 34.05878, 40],
35
+ [-118.36895, 34.05877, 40],
36
+ [-118.36884, 34.05876, 40],
37
+ [-118.36873, 34.05875, 40],
38
+ [-118.36866, 34.05874, 40],
39
+ [-118.3687, 34.05866, 40],
40
+ [-118.36874, 34.05858, 40],
41
+ [-118.36878, 34.0585, 40],
42
+ [-118.36882, 34.05842, 40],
43
+ [-118.36886, 34.05834, 40],
44
+ [-118.3689, 34.05826, 40],
45
+ [-118.36894, 34.05818, 40],
46
+ [-118.369, 34.05806, 40]
47
+ ],
48
+ [
49
+ [-118.35043, 34.0392, 30],
50
+ [-118.35047, 34.03911, 30],
51
+ [-118.35051, 34.03902, 30],
52
+ [-118.35055, 34.03893, 30],
53
+ [-118.35057, 34.03887, 30],
54
+ [-118.35045, 34.03885, 30],
55
+ [-118.35033, 34.03883, 30],
56
+ [-118.35021, 34.03881, 30],
57
+ [-118.35009, 34.03879, 30],
58
+ [-118.35002, 34.03878, 30],
59
+ [-118.35006, 34.03869, 30],
60
+ [-118.3501, 34.0386, 30],
61
+ [-118.35014, 34.03851, 30],
62
+ [-118.35018, 34.03842, 30],
63
+ [-118.35022, 34.03833, 30],
64
+ [-118.35026, 34.03824, 30],
65
+ [-118.3503, 34.03815, 30],
66
+ [-118.35034, 34.03806, 30],
67
+ [-118.35038, 34.03797, 30],
68
+ [-118.35042, 34.03788, 30],
69
+ [-118.35046, 34.03779, 30],
70
+ [-118.3505, 34.03768, 30]
71
+ ]]
72
+ }
73
+ }]
74
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "type": "FeatureCollection",
3
+ "features": [{
4
+ "type": "Feature",
5
+ "geometry": {
6
+ "type": "MultiPoint",
7
+ "coordinates": [
8
+ [-118.41585, 34.06253, 80],
9
+ [-118.4158, 34.06256, 80],
10
+ [-118.41575, 34.06259, 80]
11
+ ]
12
+ }
13
+ }]
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "FeatureCollection",
3
+ "features": [{
4
+ "type": "Feature",
5
+ "geometry": {
6
+ "type": "Point",
7
+ "coordinates": [-118.41585, 34.06253, 80]
8
+ }
9
+ }, {
10
+ "type": "Feature",
11
+ "geometry": {
12
+ "type": "Point",
13
+ "coordinates": [-118.36855, 34.05844, 40]
14
+ }
15
+ }, {
16
+ "type": "Feature",
17
+ "geometry": {
18
+ "type": "Point",
19
+ "coordinates": [-118.35043, 34.0392, 30]
20
+ }
21
+ }]
22
+ }
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'gpx'
5
+ require 'json'
6
+
7
+ class GeojsonTest < Minitest::Test
8
+ # Test passing a file name
9
+ def test_geojson_file_name_as_param
10
+ file_name = "#{File.dirname(__FILE__)}/geojson_files/line_string_data.json"
11
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file_name)
12
+ assert_equal(1, gpx_file.tracks.size)
13
+ end
14
+
15
+ # Test passing a file
16
+ def test_geojson_file_as_param
17
+ file_name = "#{File.dirname(__FILE__)}/geojson_files/line_string_data.json"
18
+ file = File.new(file_name, 'r')
19
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
20
+ assert_equal(1, gpx_file.tracks.size)
21
+ end
22
+
23
+ def test_raises_arg_error_when_no_params
24
+ assert_raises(ArgumentError) do
25
+ GPX::GeoJSON.convert_to_gpx
26
+ end
27
+ end
28
+
29
+ # Test that lat/lon allocated correctly
30
+ def test_point_to_waypoint
31
+ pt = [-118, 34]
32
+ waypoint = GPX::GeoJSON.send(:point_to_waypoint, pt, nil)
33
+ assert_equal(34, waypoint.lat)
34
+ assert_equal(-118, waypoint.lon)
35
+ end
36
+
37
+ # Test that lat/lon allocated correctly
38
+ def test_point_to_trackpoint
39
+ pt = [-118, 34]
40
+ waypoint = GPX::GeoJSON.send(:point_to_track_point, pt, nil)
41
+ assert_equal(34, waypoint.lat)
42
+ assert_equal(-118, waypoint.lon)
43
+ end
44
+
45
+ def test_line_string_functionality
46
+ file = File.join(File.dirname(__FILE__), 'geojson_files/line_string_data.json')
47
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
48
+
49
+ assert_equal(1, gpx_file.tracks.size)
50
+ assert_equal(3, gpx_file.tracks.first.segments.size)
51
+ pts_size = gpx_file.tracks.first.segments[0].points.size +
52
+ gpx_file.tracks.first.segments[1].points.size +
53
+ gpx_file.tracks.first.segments[2].points.size
54
+ assert_equal(58, pts_size)
55
+ end
56
+
57
+ def test_multi_line_string_functionality
58
+ file = File.join(File.dirname(__FILE__), 'geojson_files/multi_line_string_data.json')
59
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
60
+ assert_equal(1, gpx_file.tracks.size)
61
+ assert_equal(3, gpx_file.tracks.first.segments.size)
62
+ pts_size = gpx_file.tracks.first.segments[0].points.size +
63
+ gpx_file.tracks.first.segments[1].points.size +
64
+ gpx_file.tracks.first.segments[2].points.size
65
+ assert_equal(58, pts_size)
66
+ end
67
+
68
+ def test_point_functionality
69
+ file = File.join(File.dirname(__FILE__), 'geojson_files/point_data.json')
70
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
71
+ assert_equal(3, gpx_file.waypoints.size)
72
+ end
73
+
74
+ def test_multi_point_functionality
75
+ file = File.join(File.dirname(__FILE__), 'geojson_files/multi_point_data.json')
76
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
77
+ assert_equal(3, gpx_file.waypoints.size)
78
+ end
79
+
80
+ def test_combined_functionality
81
+ file = File.join(File.dirname(__FILE__), 'geojson_files/combined_data.json')
82
+ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
83
+
84
+ # 1 for all LineStrings, 1 for MultiLineString
85
+ assert_equal(2, gpx_file.tracks.size)
86
+ assert_equal(3, gpx_file.tracks.first.segments.size)
87
+ assert_equal(2, gpx_file.tracks.last.segments.size)
88
+ pt_sum = gpx_file.tracks.inject(0) { |sum, trk| sum + trk.points.size }
89
+ assert_equal(16, pt_sum)
90
+ assert_equal(4, gpx_file.waypoints.size)
91
+ end
92
+ end