gpx 1.0.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +37 -0
- data/.rubocop +1 -0
- data/.rubocop.yml +2 -5
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +4 -5
- data/CHANGELOG.md +14 -0
- data/Gemfile +2 -0
- data/README.md +21 -5
- data/Rakefile +7 -0
- data/UPGRADING.md +7 -0
- data/bin/gpx_distance +2 -0
- data/bin/gpx_smooth +5 -2
- data/gpx.gemspec +2 -2
- data/lib/gpx/bounds.rb +3 -0
- data/lib/gpx/geo_json.rb +199 -0
- data/lib/gpx/gpx.rb +2 -0
- data/lib/gpx/gpx_file.rb +53 -51
- data/lib/gpx/magellan_track_log.rb +3 -1
- data/lib/gpx/point.rb +5 -1
- data/lib/gpx/route.rb +4 -1
- data/lib/gpx/segment.rb +14 -9
- data/lib/gpx/track.rb +11 -4
- data/lib/gpx/track_point.rb +2 -0
- data/lib/gpx/version.rb +3 -1
- data/lib/gpx/waypoint.rb +3 -0
- data/lib/gpx.rb +3 -1
- data/tests/geojson_files/combined_data.json +68 -0
- data/tests/geojson_files/line_string_data.json +83 -0
- data/tests/geojson_files/multi_line_string_data.json +74 -0
- data/tests/geojson_files/multi_point_data.json +14 -0
- data/tests/geojson_files/point_data.json +22 -0
- data/tests/geojson_test.rb +92 -0
- data/tests/gpx10_test.rb +2 -0
- data/tests/gpx_file_test.rb +2 -0
- data/tests/gpx_files/one_segment_mixed_times.gpx +884 -0
- data/tests/gpx_files/routes_without_names.gpx +29 -0
- data/tests/magellan_test.rb +2 -0
- data/tests/output_test.rb +3 -1
- data/tests/route_test.rb +52 -0
- data/tests/segment_test.rb +13 -1
- data/tests/track_file_test.rb +3 -0
- data/tests/track_point_test.rb +2 -0
- data/tests/track_test.rb +2 -0
- data/tests/waypoint_test.rb +2 -0
- metadata +25 -9
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# This class will parse the lat/lon and time data from a Magellan track log,
|
3
5
|
# which is a NMEA formatted CSV list of points.
|
@@ -49,7 +51,7 @@ module GPX
|
|
49
51
|
lat = -lat if lat_hemi == 'S'
|
50
52
|
|
51
53
|
lon_deg = row[LON][0..2]
|
52
|
-
lon_min = row[LON][3
|
54
|
+
lon_min = row[LON][3..]
|
53
55
|
lon_hemi = row[LON_HEMI]
|
54
56
|
|
55
57
|
lon = lon_deg.to_f + (lon_min.to_f / 60.0)
|
data/lib/gpx/point.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# The base class for all points. Trackpoint and Waypoint both descend from this base class.
|
3
5
|
class Point < Base
|
@@ -10,6 +12,7 @@ module GPX
|
|
10
12
|
# addition, you can pass an XML element to this initializer, and the
|
11
13
|
# relevant info will be parsed out.
|
12
14
|
def initialize(opts = { lat: 0.0, lon: 0.0, elevation: 0.0, time: Time.now })
|
15
|
+
super()
|
13
16
|
@gpx_file = opts[:gpx_file]
|
14
17
|
if opts[:element]
|
15
18
|
elem = opts[:element]
|
@@ -18,7 +21,8 @@ module GPX
|
|
18
21
|
@latr = (D_TO_R * @lat)
|
19
22
|
@lonr = (D_TO_R * @lon)
|
20
23
|
# '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
|
21
|
-
@time = (
|
24
|
+
@time = (
|
25
|
+
begin
|
22
26
|
Time.xmlschema(elem.at('time').inner_text)
|
23
27
|
rescue StandardError
|
24
28
|
nil
|
data/lib/gpx/route.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# A Route in GPX is very similar to a Track, but it is created by a user
|
3
5
|
# from a series of Waypoints, whereas a Track is created by the GPS device
|
@@ -7,10 +9,11 @@ module GPX
|
|
7
9
|
|
8
10
|
# Initialize a Route from a XML::Node.
|
9
11
|
def initialize(opts = {})
|
12
|
+
super()
|
10
13
|
if opts[:gpx_file] && opts[:element]
|
11
14
|
rte_element = opts[:element]
|
12
15
|
@gpx_file = opts[:gpx_file]
|
13
|
-
@name = rte_element.at('name')
|
16
|
+
@name = rte_element.at('name')&.inner_text
|
14
17
|
@points = []
|
15
18
|
rte_element.search('rtept').each do |point|
|
16
19
|
@points << Point.new(element: point, gpx_file: @gpx_file)
|
data/lib/gpx/segment.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# A segment is the basic container in a GPX file. A Segment contains points
|
3
5
|
# (in this lib, they're called TrackPoints). A Track contains Segments. An
|
@@ -10,6 +12,7 @@ module GPX
|
|
10
12
|
# If a XML::Node object is passed-in, this will initialize a new
|
11
13
|
# Segment based on its contents. Otherwise, a blank Segment is created.
|
12
14
|
def initialize(opts = {})
|
15
|
+
super()
|
13
16
|
@gpx_file = opts[:gpx_file]
|
14
17
|
@track = opts[:track]
|
15
18
|
@points = []
|
@@ -22,7 +25,8 @@ module GPX
|
|
22
25
|
@bounds = Bounds.new
|
23
26
|
|
24
27
|
segment_element = opts[:element]
|
25
|
-
return unless segment_element
|
28
|
+
return unless segment_element.is_a?(Nokogiri::XML::Node)
|
29
|
+
|
26
30
|
segment_element.search('trkpt').each do |trkpt|
|
27
31
|
pt = TrackPoint.new(element: trkpt, segment: self, gpx_file: @gpx_file)
|
28
32
|
append_point(pt)
|
@@ -33,8 +37,8 @@ module GPX
|
|
33
37
|
def append_point(pt)
|
34
38
|
last_pt = @points[-1]
|
35
39
|
if pt.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)
|
40
|
+
@earliest_point = pt if @earliest_point.nil? || (@earliest_point.time && pt.time < @earliest_point.time)
|
41
|
+
@latest_point = pt if @latest_point.nil? || (@latest_point.time && pt.time > @latest_point.time)
|
38
42
|
else
|
39
43
|
# when no time information in data, we consider the points are ordered
|
40
44
|
@earliest_point = @points[0]
|
@@ -91,6 +95,7 @@ module GPX
|
|
91
95
|
last_pt = nil
|
92
96
|
points.each do |pt|
|
93
97
|
next if yield(pt)
|
98
|
+
|
94
99
|
keep_points << pt
|
95
100
|
update_meta_data(pt, last_pt)
|
96
101
|
last_pt = pt
|
@@ -124,7 +129,7 @@ module GPX
|
|
124
129
|
elsif indicator.is_a?(Time)
|
125
130
|
closest_point(indicator)
|
126
131
|
else
|
127
|
-
raise
|
132
|
+
raise ArgumentError, 'find_end_point_by_time_or_offset requires an argument of type Time or Integer'
|
128
133
|
end
|
129
134
|
end
|
130
135
|
|
@@ -174,9 +179,9 @@ module GPX
|
|
174
179
|
|
175
180
|
protected
|
176
181
|
|
177
|
-
# rubocop:disable Style/GuardClause
|
178
182
|
def find_closest(pts, time)
|
179
183
|
return pts.first if pts.size == 1
|
184
|
+
|
180
185
|
midpoint = pts.size / 2
|
181
186
|
if pts.size == 2
|
182
187
|
diff_1 = pts[0].time - time
|
@@ -184,14 +189,13 @@ module GPX
|
|
184
189
|
return (diff_1 < diff_2 ? pts[0] : pts[1])
|
185
190
|
end
|
186
191
|
if (time >= pts[midpoint].time) && (time <= pts[midpoint + 1].time)
|
187
|
-
|
192
|
+
pts[midpoint]
|
188
193
|
elsif time <= pts[midpoint].time
|
189
|
-
|
194
|
+
find_closest(pts[0..midpoint], time)
|
190
195
|
else
|
191
|
-
|
196
|
+
find_closest(pts[(midpoint + 1)..], time)
|
192
197
|
end
|
193
198
|
end
|
194
|
-
# rubocop:enable Style/GuardClause
|
195
199
|
|
196
200
|
# Calculate the Haversine distance between two points. This is the method
|
197
201
|
# the library uses to calculate the cumulative distance of GPX files.
|
@@ -231,6 +235,7 @@ module GPX
|
|
231
235
|
@bounds.add(pt)
|
232
236
|
|
233
237
|
return unless last_pt
|
238
|
+
|
234
239
|
@distance += haversine_distance(last_pt, pt)
|
235
240
|
@duration += pt.time - last_pt.time if pt.time && last_pt.time
|
236
241
|
end
|
data/lib/gpx/track.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# In GPX, a single Track can hold multiple Segments, each of which hold
|
3
5
|
# multiple points (in this library, those points are instances of
|
@@ -12,6 +14,7 @@ module GPX
|
|
12
14
|
# Initialize a track from a XML::Node, or, if no :element option is
|
13
15
|
# passed, initialize a blank Track object.
|
14
16
|
def initialize(opts = {})
|
17
|
+
super()
|
15
18
|
@gpx_file = opts[:gpx_file]
|
16
19
|
@segments = []
|
17
20
|
@points = []
|
@@ -20,17 +23,20 @@ module GPX
|
|
20
23
|
return unless opts[:element]
|
21
24
|
|
22
25
|
trk_element = opts[:element]
|
23
|
-
@name = (
|
26
|
+
@name = (
|
27
|
+
begin
|
24
28
|
trk_element.at('name').inner_text
|
25
29
|
rescue StandardError
|
26
30
|
''
|
27
31
|
end)
|
28
|
-
@comment = (
|
32
|
+
@comment = (
|
33
|
+
begin
|
29
34
|
trk_element.at('cmt').inner_text
|
30
35
|
rescue StandardError
|
31
36
|
''
|
32
37
|
end)
|
33
|
-
@description = (
|
38
|
+
@description = (
|
39
|
+
begin
|
34
40
|
trk_element.at('desc').inner_text
|
35
41
|
rescue StandardError
|
36
42
|
''
|
@@ -44,6 +50,7 @@ module GPX
|
|
44
50
|
# Append a segment to this track, updating its meta data along the way.
|
45
51
|
def append_segment(seg)
|
46
52
|
return if seg.points.empty?
|
53
|
+
|
47
54
|
update_meta_data(seg)
|
48
55
|
@segments << seg
|
49
56
|
end
|
@@ -88,7 +95,7 @@ module GPX
|
|
88
95
|
# Returns true if this track has no points in it. This should return
|
89
96
|
# true even when the track has empty segments.
|
90
97
|
def empty?
|
91
|
-
(points.nil? || points.
|
98
|
+
(points.nil? || points.empty?)
|
92
99
|
end
|
93
100
|
|
94
101
|
# Prints out a friendly summary of this track (sans points). Useful for
|
data/lib/gpx/track_point.rb
CHANGED
data/lib/gpx/version.rb
CHANGED
data/lib/gpx/waypoint.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GPX
|
2
4
|
# This class supports the concept of a waypoint. Beware that this class has
|
3
5
|
# not seen much use yet, since WalkingBoss does not use waypoints right now.
|
@@ -5,6 +7,7 @@ module GPX
|
|
5
7
|
SUB_ELEMENTS = %w[ele magvar geoidheight name cmt desc src link sym type fix sat hdop vdop pdop ageofdgpsdata dgpsid extensions].freeze
|
6
8
|
|
7
9
|
attr_reader :gpx_file
|
10
|
+
|
8
11
|
SUB_ELEMENTS.each { |sub_el| attr_accessor sub_el.to_sym }
|
9
12
|
|
10
13
|
# Not implemented
|
data/lib/gpx.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'time'
|
2
4
|
require 'nokogiri'
|
3
5
|
|
4
6
|
require File.expand_path('gpx/version', __dir__)
|
5
|
-
|
6
7
|
require File.expand_path('gpx/gpx', __dir__)
|
7
8
|
require File.expand_path('gpx/gpx_file', __dir__)
|
8
9
|
require File.expand_path('gpx/bounds', __dir__)
|
@@ -13,3 +14,4 @@ require File.expand_path('gpx/point', __dir__)
|
|
13
14
|
require File.expand_path('gpx/track_point', __dir__)
|
14
15
|
require File.expand_path('gpx/waypoint', __dir__)
|
15
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,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
|
data/tests/gpx10_test.rb
CHANGED