gpx 1.1.0 → 1.1.2
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 +4 -3
- data/.rubocop +1 -0
- data/.rubocop.yml +4 -1
- data/.ruby-version +1 -1
- data/.tool-versions +1 -0
- data/.travis.yml +1 -3
- data/CHANGELOG.md +14 -1
- data/README.md +34 -7
- data/UPGRADING.md +7 -0
- data/gpx.gemspec +1 -1
- data/lib/gpx/bounds.rb +1 -1
- data/lib/gpx/geo_json.rb +30 -16
- data/lib/gpx/gpx_file.rb +1 -4
- data/lib/gpx/magellan_track_log.rb +1 -1
- data/lib/gpx/route.rb +1 -1
- data/lib/gpx/segment.rb +3 -3
- data/lib/gpx/track.rb +1 -1
- data/lib/gpx/version.rb +1 -1
- data/tests/geojson_files/line_string_data.json +11 -2
- data/tests/geojson_files/multi_line_string_data.json +3 -0
- data/tests/geojson_files/multi_point_data.json +3 -0
- data/tests/geojson_files/point_data.json +9 -0
- data/tests/geojson_test.rb +63 -0
- data/tests/gpx_file_test.rb +34 -29
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94b41dda1f7722e6a90e261b66420e08074a953c866f7c4b32947ff41046bbcb
|
4
|
+
data.tar.gz: 8aec6ca78168bab0c9ec5dd1d8e689387cfe700aa4b3984639ba9d8f9bcf4095
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96c15693a26a49344ffb7e552d352fc342ee033af8cf62219295e4b3a3334ee9a3ceb201c168a4fbd079647714e0e10dd8a5653842c5ac1c2ce5442946622063
|
7
|
+
data.tar.gz: 9e30c74ad0165287406fa0c322651fd8ab326bdf712f8563097c11451bb7601cc245acc4b74cc5d9d40e059126583ce421df0c4950183bc36833add6f5862db2
|
data/.github/workflows/ruby.yml
CHANGED
@@ -19,16 +19,17 @@ jobs:
|
|
19
19
|
|
20
20
|
runs-on: ubuntu-latest
|
21
21
|
strategy:
|
22
|
+
fail-fast: true
|
22
23
|
matrix:
|
23
|
-
ruby-version: ['2.7', '3.0', '3.1']
|
24
|
+
ruby-version: ['2.7', '3.0', '3.1', '3.2']
|
24
25
|
|
25
26
|
steps:
|
26
|
-
- uses: actions/checkout@
|
27
|
+
- uses: actions/checkout@v4
|
27
28
|
- name: Set up Ruby
|
28
29
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
29
30
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
30
31
|
# uses: ruby/setup-ruby@v1
|
31
|
-
uses: ruby/setup-ruby@
|
32
|
+
uses: ruby/setup-ruby@v1.159.0
|
32
33
|
with:
|
33
34
|
ruby-version: ${{ matrix.ruby-version }}
|
34
35
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
data/.rubocop
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--server
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.7
|
3
3
|
|
4
4
|
Style/Alias:
|
5
5
|
Enabled: false
|
@@ -65,6 +65,9 @@ Style/NegatedWhile:
|
|
65
65
|
Enabled: false
|
66
66
|
StyleGuide: http://relaxed.ruby.style/#stylenegatedwhile
|
67
67
|
|
68
|
+
Style/OptionalBooleanParameter:
|
69
|
+
Enabled: false
|
70
|
+
|
68
71
|
Style/ParallelAssignment:
|
69
72
|
Enabled: false
|
70
73
|
StyleGuide: http://relaxed.ruby.style/#styleparallelassignment
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.2.2
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.2.2
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,23 @@
|
|
1
|
-
## [1.1.
|
1
|
+
## [1.1.2] - 2024-07-26
|
2
|
+
|
3
|
+
* Adds ability to address various GeoJSON properties when performing GeoJSON to GPX conversion. (#53 via @niborg)
|
4
|
+
* Allow anything that responds to `read` for GPXFile input. (#55 via @hiroaki)
|
5
|
+
|
6
|
+
## [1.1.1] - 2023-05-19
|
7
|
+
|
8
|
+
* updates CI, minimal Ruby version now 2.7, updates tooling like rubocop and GitHub actions
|
9
|
+
* adds support for Ruby 3.2
|
10
|
+
* adds UPGRADING.md to document changes between versions
|
11
|
+
|
12
|
+
## [1.1.0] - 2023-05-18
|
13
|
+
|
2
14
|
* Specify UTF-8 encoding for XML encoding (#35 via @sh1nduu)
|
3
15
|
* Added GeoJSON conversion (#38 via @tyrauber and @niborg)
|
4
16
|
* Support Ruby 3 (#43 via @LocoDelAssembly)
|
5
17
|
* Fix nil-to-Time comparison (#46 via @frodrigo)
|
6
18
|
* Fix bug when <rte> GPX file does not specify <name> tag (#41 via @niborg)
|
7
19
|
* Drop Ruby 2.5 and 2.6 from CI (#50 via @niborg)
|
20
|
+
|
8
21
|
## [1.0.0] - 2018-03-06
|
9
22
|
|
10
23
|
* Fix duplication of points on appending segment to track (#20 via @niborg)
|
data/README.md
CHANGED
@@ -6,25 +6,37 @@
|
|
6
6
|
## What It Does
|
7
7
|
|
8
8
|
This library reads GPX files and provides an API for reading and manipulating
|
9
|
-
the data as objects.
|
9
|
+
the data as objects. For more info on the GPX format, see
|
10
10
|
http://www.topografix.com/gpx.asp.
|
11
11
|
|
12
12
|
In addition to parsing GPX files, this library is capable of converting
|
13
13
|
Magellan NMEA files to GPX, converting GeoJSON data to GPX, and writing
|
14
|
-
new GPX files.
|
14
|
+
new GPX files. It can crop and delete rectangular areas within a file,
|
15
15
|
and it also calculates some meta-data about the tracks and points in a file (such as distance, duration, average speed, etc).
|
16
16
|
|
17
17
|
## Requirements
|
18
18
|
|
19
|
-
As of `1.
|
19
|
+
- As of `1.1.1`, `gpx` requires at least Ruby 2.7 to run.
|
20
|
+
- As of `1.0.0`, `gpx` requires at least Ruby 2.2 to run.
|
20
21
|
|
21
22
|
## Installation
|
23
|
+
|
22
24
|
Add to your gemfile:
|
25
|
+
|
23
26
|
```
|
24
27
|
gem 'gpx'
|
25
28
|
```
|
29
|
+
|
26
30
|
## Examples
|
27
31
|
|
32
|
+
Initialize a `GPXFile` object with either a file-like object or a string representation:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
gpx = GPX::GPXFile.new(:gpx_file => string_io) # Anything that responds to `read`
|
36
|
+
gpx = GPX::GPXFile.new(:gpx_file => path_to_a_file)
|
37
|
+
gpx = GPX::GPXFile.new(:gpx_data => some_string)
|
38
|
+
```
|
39
|
+
|
28
40
|
Reading a GPX file, and cropping its contents to a given area:
|
29
41
|
|
30
42
|
```ruby
|
@@ -35,6 +47,7 @@ gpx.write(filename) # Save it
|
|
35
47
|
```
|
36
48
|
|
37
49
|
Converting a Magellan track log to GPX:
|
50
|
+
|
38
51
|
```ruby
|
39
52
|
if GPX::MagellanTrackLog::is_magellan_file?(filename)
|
40
53
|
GPX::MagellanTrackLog::convert_to_gpx(filename, "#{filename}.gpx")
|
@@ -43,6 +56,7 @@ end
|
|
43
56
|
|
44
57
|
Converting GeoJSON data to GPX can be achieved by providing a
|
45
58
|
file path, file, or the data in string format:
|
59
|
+
|
46
60
|
```ruby
|
47
61
|
# Converting from a file name
|
48
62
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: 'mygeojsonfile.json')
|
@@ -50,9 +64,23 @@ gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: 'mygeojsonfile.json')
|
|
50
64
|
# Converting from a string
|
51
65
|
data = JSON.generate(my_geojson_hash)
|
52
66
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_data: data)
|
67
|
+
|
68
|
+
# The above won't transfer anything but coordinate values. If you want to
|
69
|
+
# transfer ad hoc "properties" information, you can specify an object that
|
70
|
+
# responds to `call` to manipulate GPX data structures as follows:
|
71
|
+
gpx_file = GPX::GeoJSON.convert_to_gpx(
|
72
|
+
geojson_data: data,
|
73
|
+
line_string_feature_to_segment: ->(ls, seg) { seg.distance = ls["properties"]["distance"] },
|
74
|
+
multi_line_string_feature_to_track: lambda { |mls, track|
|
75
|
+
track.name = mls["properties"]["name"]
|
76
|
+
},
|
77
|
+
point_feature_to_waypoint: ->(pt, wpt) { wpt.name = pt["properties"]["name"] }
|
78
|
+
multi_point_feature_to_waypoint: ->(mpt, wpt) { wpt.sym = mpt["properties"]["icon"] }
|
79
|
+
)
|
53
80
|
```
|
54
81
|
|
55
82
|
Exporting an ActiveRecord to GPXFile (as Waypoints)
|
83
|
+
|
56
84
|
```ruby
|
57
85
|
#
|
58
86
|
# Our active record in this example is called stop
|
@@ -97,12 +125,11 @@ Mime::Type.register "application/gpx+xml", :gpx
|
|
97
125
|
|
98
126
|
You have a complete example on how to create a gpx file from scratch on `tests/output_text.rb`.
|
99
127
|
|
100
|
-
|
101
128
|
## Notes
|
102
129
|
|
103
130
|
This library was written to bridge the gap between my Garmin Geko
|
104
|
-
and my website, WalkingBoss.org (RIP).
|
105
|
-
work-in-progress than an attempt at full GPX compliance.
|
131
|
+
and my website, WalkingBoss.org (RIP). For that reason, it has always been more of a
|
132
|
+
work-in-progress than an attempt at full GPX compliance. The track side of the
|
106
133
|
library has seen much more use than the route/waypoint side, so if you're doing
|
107
134
|
something with routes or waypoints, you may need to tweak some things.
|
108
135
|
|
@@ -112,7 +139,7 @@ working with tracks from several days or weeks.
|
|
112
139
|
|
113
140
|
Finally, it should be noted that none of the distance/speed calculation or
|
114
141
|
crop/delete code has been tested under International Date Line-crossing
|
115
|
-
conditions.
|
142
|
+
conditions. That particular part of the code will likely be unreliable if
|
116
143
|
you're zig-zagging across 180 degrees longitude routinely.
|
117
144
|
|
118
145
|
## License
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Upgrading
|
2
|
+
|
3
|
+
You will find all the information you need to upgrade from one version to another here.
|
4
|
+
|
5
|
+
## Version 1.0.0 to 1.1.1
|
6
|
+
|
7
|
+
Please make sure, that you need at least Ruby 2.7.0 to use this gem now. As support for Ruby versions below 2.7.0 has been dropped.
|
data/gpx.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = 'A basic API for reading and writing GPX files.'
|
13
13
|
s.description = 'A basic API for reading and writing GPX files.'
|
14
14
|
|
15
|
-
s.required_ruby_version = '>= 2.
|
15
|
+
s.required_ruby_version = '>= 2.7', '< 4'
|
16
16
|
|
17
17
|
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
18
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
data/lib/gpx/bounds.rb
CHANGED
@@ -28,7 +28,7 @@ module GPX
|
|
28
28
|
|
29
29
|
# Returns true if the pt is within these bounds.
|
30
30
|
def contains?(pt)
|
31
|
-
(
|
31
|
+
(pt.lat >= min_lat) && (pt.lat <= max_lat) && (pt.lon >= min_lon) && (pt.lon <= max_lon)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Adds an item to itself, expanding its min/max lat/lon as needed to
|
data/lib/gpx/geo_json.rb
CHANGED
@@ -34,8 +34,8 @@ module GPX
|
|
34
34
|
def convert_to_gpx(opts = {})
|
35
35
|
geojson = geojson_data_from(opts)
|
36
36
|
gpx_file = GPX::GPXFile.new
|
37
|
-
add_tracks_to(gpx_file, geojson)
|
38
|
-
add_waypoints_to(gpx_file, geojson)
|
37
|
+
add_tracks_to(gpx_file, geojson, opts)
|
38
|
+
add_waypoints_to(gpx_file, geojson, opts)
|
39
39
|
gpx_file
|
40
40
|
end
|
41
41
|
|
@@ -61,32 +61,35 @@ module GPX
|
|
61
61
|
JSON.parse(data)
|
62
62
|
end
|
63
63
|
|
64
|
-
def add_tracks_to(gpx_file, geojson)
|
65
|
-
tracks = [line_strings_to_track(geojson)] +
|
66
|
-
multi_line_strings_to_tracks(geojson)
|
64
|
+
def add_tracks_to(gpx_file, geojson, opts)
|
65
|
+
tracks = [line_strings_to_track(geojson, opts)] +
|
66
|
+
multi_line_strings_to_tracks(geojson, opts)
|
67
67
|
tracks.compact!
|
68
68
|
gpx_file.tracks += tracks
|
69
69
|
gpx_file.tracks.each { |t| gpx_file.update_meta_data(t) }
|
70
70
|
end
|
71
71
|
|
72
|
-
def add_waypoints_to(gpx_file, geojson)
|
72
|
+
def add_waypoints_to(gpx_file, geojson, opts)
|
73
73
|
gpx_file.waypoints +=
|
74
|
-
points_to_waypoints(geojson, gpx_file) +
|
75
|
-
multi_points_to_waypoints(geojson, gpx_file)
|
74
|
+
points_to_waypoints(geojson, gpx_file, opts) +
|
75
|
+
multi_points_to_waypoints(geojson, gpx_file, opts)
|
76
76
|
end
|
77
77
|
|
78
78
|
# Converts GeoJSON 'LineString' features.
|
79
79
|
# Current strategy is to convert each LineString into a
|
80
80
|
# Track Segment, returning a Track for all LineStrings.
|
81
81
|
#
|
82
|
-
def line_strings_to_track(geojson)
|
82
|
+
def line_strings_to_track(geojson, opts)
|
83
83
|
line_strings = line_strings_in(geojson)
|
84
84
|
return nil unless line_strings.any?
|
85
85
|
|
86
86
|
track = GPX::Track.new
|
87
87
|
line_strings.each do |ls|
|
88
88
|
coords = ls['geometry']['coordinates']
|
89
|
-
|
89
|
+
segment = coords_to_segment(coords)
|
90
|
+
|
91
|
+
opts[:line_string_feature_to_segment]&.call(ls, segment)
|
92
|
+
track.append_segment(segment)
|
90
93
|
end
|
91
94
|
track
|
92
95
|
end
|
@@ -96,15 +99,18 @@ module GPX
|
|
96
99
|
# into a Track, with each set of LineString coordinates
|
97
100
|
# within a MultiLineString a Track Segment.
|
98
101
|
#
|
99
|
-
def multi_line_strings_to_tracks(geojson)
|
102
|
+
def multi_line_strings_to_tracks(geojson, opts)
|
100
103
|
tracks = []
|
101
104
|
multi_line_strings_in(geojson).each do |mls|
|
102
105
|
track = GPX::Track.new
|
103
106
|
mls['geometry']['coordinates'].each do |coords|
|
104
107
|
seg = coords_to_segment(coords)
|
105
108
|
seg.track = track
|
109
|
+
|
106
110
|
track.append_segment(seg)
|
107
111
|
end
|
112
|
+
|
113
|
+
opts[:multi_line_string_feature_to_track]&.call(mls, track)
|
108
114
|
tracks << track
|
109
115
|
end
|
110
116
|
tracks
|
@@ -114,10 +120,14 @@ module GPX
|
|
114
120
|
# Current strategy is to convert each Point
|
115
121
|
# feature into a GPX waypoint.
|
116
122
|
#
|
117
|
-
def points_to_waypoints(geojson, gpx_file)
|
123
|
+
def points_to_waypoints(geojson, gpx_file, opts)
|
118
124
|
points_in(geojson).reduce([]) do |acc, pt|
|
119
125
|
coords = pt['geometry']['coordinates']
|
120
|
-
|
126
|
+
waypoint = point_to_waypoint(coords, gpx_file)
|
127
|
+
|
128
|
+
opts[:point_feature_to_waypoint]&.call(pt, waypoint)
|
129
|
+
|
130
|
+
acc << waypoint
|
121
131
|
end
|
122
132
|
end
|
123
133
|
|
@@ -132,10 +142,14 @@ module GPX
|
|
132
142
|
# series of turn points leading to a destination."
|
133
143
|
# See http://www.topografix.com/gpx/1/1/#type_rteType
|
134
144
|
#
|
135
|
-
def multi_points_to_waypoints(geojson, gpx_file)
|
136
|
-
multi_points_in(geojson).
|
145
|
+
def multi_points_to_waypoints(geojson, gpx_file, opts)
|
146
|
+
multi_points_in(geojson).each_with_object([]) do |mpt, acc|
|
137
147
|
mpt['geometry']['coordinates'].each do |coords|
|
138
|
-
|
148
|
+
waypoint = point_to_waypoint(coords, gpx_file)
|
149
|
+
|
150
|
+
opts[:multi_point_feature_to_waypoint]&.call(mpt, waypoint)
|
151
|
+
|
152
|
+
acc << waypoint
|
139
153
|
end
|
140
154
|
end
|
141
155
|
end
|
data/lib/gpx/gpx_file.rb
CHANGED
@@ -35,7 +35,7 @@ module GPX
|
|
35
35
|
if opts[:gpx_file] || opts[:gpx_data]
|
36
36
|
if opts[:gpx_file]
|
37
37
|
gpx_file = opts[:gpx_file]
|
38
|
-
gpx_file = File.open(gpx_file) unless gpx_file.
|
38
|
+
gpx_file = File.open(gpx_file) unless gpx_file.respond_to?(:read)
|
39
39
|
@xml = Nokogiri::XML(gpx_file)
|
40
40
|
else
|
41
41
|
@xml = Nokogiri::XML(opts[:gpx_data])
|
@@ -194,8 +194,6 @@ module GPX
|
|
194
194
|
@moving_duration = 0.0
|
195
195
|
end
|
196
196
|
|
197
|
-
# rubocop:disable Style/OptionalBooleanParameter
|
198
|
-
|
199
197
|
# Updates the meta data for this GPX file. Meta data includes the
|
200
198
|
# bounds, the high and low points, and the distance. This is useful when
|
201
199
|
# you modify the GPX data (i.e. by adding or deleting points) and you
|
@@ -222,7 +220,6 @@ module GPX
|
|
222
220
|
doc = generate_xml_doc
|
223
221
|
doc.to_xml
|
224
222
|
end
|
225
|
-
# rubocop:enable Style/OptionalBooleanParameter
|
226
223
|
|
227
224
|
def inspect
|
228
225
|
"<#{self.class.name}:...>"
|
data/lib/gpx/route.rb
CHANGED
data/lib/gpx/segment.rb
CHANGED
@@ -62,7 +62,7 @@ module GPX
|
|
62
62
|
|
63
63
|
# Returns true if the given time is within this Segment.
|
64
64
|
def contains_time?(time)
|
65
|
-
(
|
65
|
+
(time >= @earliest_point.time) && (time <= @latest_point.time)
|
66
66
|
rescue StandardError
|
67
67
|
false
|
68
68
|
end
|
@@ -105,7 +105,7 @@ module GPX
|
|
105
105
|
|
106
106
|
# Returns true if this Segment has no points.
|
107
107
|
def empty?
|
108
|
-
|
108
|
+
points.nil? || points.empty?
|
109
109
|
end
|
110
110
|
|
111
111
|
# Prints out a nice summary of this Segment.
|
@@ -193,7 +193,7 @@ module GPX
|
|
193
193
|
elsif time <= pts[midpoint].time
|
194
194
|
find_closest(pts[0..midpoint], time)
|
195
195
|
else
|
196
|
-
find_closest(pts[(midpoint + 1)
|
196
|
+
find_closest(pts[(midpoint + 1)..], time)
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
data/lib/gpx/track.rb
CHANGED
@@ -95,7 +95,7 @@ module GPX
|
|
95
95
|
# Returns true if this track has no points in it. This should return
|
96
96
|
# true even when the track has empty segments.
|
97
97
|
def empty?
|
98
|
-
|
98
|
+
points.nil? || points.empty?
|
99
99
|
end
|
100
100
|
|
101
101
|
# Prints out a friendly summary of this track (sans points). Useful for
|
data/lib/gpx/version.rb
CHANGED
@@ -24,8 +24,11 @@
|
|
24
24
|
[-118.41506, 34.06301, 80],
|
25
25
|
[-118.415, 34.06305, 80],
|
26
26
|
[-118.41494, 34.06309, 80]
|
27
|
-
|
28
|
-
|
27
|
+
]
|
28
|
+
},
|
29
|
+
"properties": {
|
30
|
+
"distance": 10
|
31
|
+
}
|
29
32
|
}, {
|
30
33
|
"type": "Feature",
|
31
34
|
"geometry": {
|
@@ -49,6 +52,9 @@
|
|
49
52
|
[-118.36894, 34.05818, 40],
|
50
53
|
[-118.369, 34.05806, 40]
|
51
54
|
]
|
55
|
+
},
|
56
|
+
"properties": {
|
57
|
+
"distance": 100
|
52
58
|
}
|
53
59
|
}, {
|
54
60
|
"type": "Feature",
|
@@ -78,6 +84,9 @@
|
|
78
84
|
[-118.35046, 34.03779, 30],
|
79
85
|
[-118.3505, 34.03768, 30]
|
80
86
|
]
|
87
|
+
},
|
88
|
+
"properties": {
|
89
|
+
"distance": 1000
|
81
90
|
}
|
82
91
|
}]
|
83
92
|
}
|
@@ -5,18 +5,27 @@
|
|
5
5
|
"geometry": {
|
6
6
|
"type": "Point",
|
7
7
|
"coordinates": [-118.41585, 34.06253, 80]
|
8
|
+
},
|
9
|
+
"properties": {
|
10
|
+
"name": "Foo"
|
8
11
|
}
|
9
12
|
}, {
|
10
13
|
"type": "Feature",
|
11
14
|
"geometry": {
|
12
15
|
"type": "Point",
|
13
16
|
"coordinates": [-118.36855, 34.05844, 40]
|
17
|
+
},
|
18
|
+
"properties": {
|
19
|
+
"name": "Bar"
|
14
20
|
}
|
15
21
|
}, {
|
16
22
|
"type": "Feature",
|
17
23
|
"geometry": {
|
18
24
|
"type": "Point",
|
19
25
|
"coordinates": [-118.35043, 34.0392, 30]
|
26
|
+
},
|
27
|
+
"properties": {
|
28
|
+
"name": "Baz"
|
20
29
|
}
|
21
30
|
}]
|
22
31
|
}
|
data/tests/geojson_test.rb
CHANGED
@@ -54,6 +54,28 @@ class GeojsonTest < Minitest::Test
|
|
54
54
|
assert_equal(58, pts_size)
|
55
55
|
end
|
56
56
|
|
57
|
+
def test_line_string_functionality_with_lambda
|
58
|
+
file = File.join(File.dirname(__FILE__), 'geojson_files/line_string_data.json')
|
59
|
+
gpx_file = GPX::GeoJSON.convert_to_gpx(
|
60
|
+
geojson_file: file,
|
61
|
+
line_string_feature_to_segment: lambda { |line_string, segment|
|
62
|
+
segment.points << GPX::Point.new(
|
63
|
+
{
|
64
|
+
lat: line_string['geometry']['coordinates'][0][1],
|
65
|
+
lon: line_string['geometry']['coordinates'][0][0]
|
66
|
+
}
|
67
|
+
)
|
68
|
+
}
|
69
|
+
)
|
70
|
+
|
71
|
+
assert_equal(1, gpx_file.tracks.size)
|
72
|
+
assert_equal(3, gpx_file.tracks.first.segments.size)
|
73
|
+
pts_size = gpx_file.tracks.first.segments[0].points.size +
|
74
|
+
gpx_file.tracks.first.segments[1].points.size +
|
75
|
+
gpx_file.tracks.first.segments[2].points.size
|
76
|
+
assert_equal(61, pts_size)
|
77
|
+
end
|
78
|
+
|
57
79
|
def test_multi_line_string_functionality
|
58
80
|
file = File.join(File.dirname(__FILE__), 'geojson_files/multi_line_string_data.json')
|
59
81
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
|
@@ -65,18 +87,59 @@ class GeojsonTest < Minitest::Test
|
|
65
87
|
assert_equal(58, pts_size)
|
66
88
|
end
|
67
89
|
|
90
|
+
def test_multi_line_string_functionality_with_lambda
|
91
|
+
file = File.join(File.dirname(__FILE__), 'geojson_files/multi_line_string_data.json')
|
92
|
+
gpx_file = GPX::GeoJSON.convert_to_gpx(
|
93
|
+
geojson_file: file,
|
94
|
+
multi_line_string_feature_to_track: lambda { |multi_line_string, segment|
|
95
|
+
segment.name = multi_line_string['properties']['name']
|
96
|
+
}
|
97
|
+
)
|
98
|
+
assert_equal(1, gpx_file.tracks.size)
|
99
|
+
assert_equal(3, gpx_file.tracks.first.segments.size)
|
100
|
+
pts_size = gpx_file.tracks.first.segments[0].points.size +
|
101
|
+
gpx_file.tracks.first.segments[1].points.size +
|
102
|
+
gpx_file.tracks.first.segments[2].points.size
|
103
|
+
assert_equal(58, pts_size)
|
104
|
+
assert_equal("Foo", gpx_file.tracks[0].name)
|
105
|
+
end
|
106
|
+
|
68
107
|
def test_point_functionality
|
69
108
|
file = File.join(File.dirname(__FILE__), 'geojson_files/point_data.json')
|
70
109
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
|
71
110
|
assert_equal(3, gpx_file.waypoints.size)
|
72
111
|
end
|
73
112
|
|
113
|
+
def test_point_functionality_with_proc
|
114
|
+
file = File.join(File.dirname(__FILE__), 'geojson_files/point_data.json')
|
115
|
+
gpx_file = GPX::GeoJSON.convert_to_gpx(
|
116
|
+
geojson_file: file,
|
117
|
+
point_feature_to_waypoint: ->(point, waypoint) { waypoint.name = point['properties']['name'] }
|
118
|
+
)
|
119
|
+
assert_equal(3, gpx_file.waypoints.size)
|
120
|
+
assert_equal('Foo', gpx_file.waypoints[0].name)
|
121
|
+
assert_equal('Bar', gpx_file.waypoints[1].name)
|
122
|
+
assert_equal('Baz', gpx_file.waypoints[2].name)
|
123
|
+
end
|
124
|
+
|
74
125
|
def test_multi_point_functionality
|
75
126
|
file = File.join(File.dirname(__FILE__), 'geojson_files/multi_point_data.json')
|
76
127
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
|
77
128
|
assert_equal(3, gpx_file.waypoints.size)
|
78
129
|
end
|
79
130
|
|
131
|
+
def test_multi_point_functionality_with_proc
|
132
|
+
file = File.join(File.dirname(__FILE__), 'geojson_files/multi_point_data.json')
|
133
|
+
gpx_file = GPX::GeoJSON.convert_to_gpx(
|
134
|
+
geojson_file: file,
|
135
|
+
multi_point_feature_to_waypoint: ->(multi_point, waypoint) { waypoint.name = multi_point['properties']['name'] }
|
136
|
+
)
|
137
|
+
assert_equal(3, gpx_file.waypoints.size)
|
138
|
+
assert_equal('Foo', gpx_file.waypoints[0].name)
|
139
|
+
assert_equal('Foo', gpx_file.waypoints[1].name)
|
140
|
+
assert_equal('Foo', gpx_file.waypoints[2].name)
|
141
|
+
end
|
142
|
+
|
80
143
|
def test_combined_functionality
|
81
144
|
file = File.join(File.dirname(__FILE__), 'geojson_files/combined_data.json')
|
82
145
|
gpx_file = GPX::GeoJSON.convert_to_gpx(geojson_file: file)
|
data/tests/gpx_file_test.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require 'gpx'
|
5
|
+
require 'stringio'
|
5
6
|
|
6
7
|
class GPXFileTest < Minitest::Test
|
7
8
|
ONE_TRACK_FILE = File.join(File.dirname(__FILE__), 'gpx_files/one_track.gpx')
|
@@ -11,39 +12,12 @@ class GPXFileTest < Minitest::Test
|
|
11
12
|
|
12
13
|
def test_load_data_from_string
|
13
14
|
gpx_file = GPX::GPXFile.new(gpx_data: File.open(ONE_TRACK_FILE).read)
|
14
|
-
|
15
|
-
assert_equal(8, gpx_file.tracks.first.segments.size)
|
16
|
-
assert_equal('ACTIVE LOG', gpx_file.tracks.first.name)
|
17
|
-
assert_equal('active_log.gpx', gpx_file.name)
|
18
|
-
assert_equal('2006-04-08T16:44:28Z', gpx_file.time.xmlschema)
|
19
|
-
assert_equal(38.681488, gpx_file.bounds.min_lat)
|
20
|
-
assert_equal(-109.606948, gpx_file.bounds.min_lon)
|
21
|
-
assert_equal(38.791759, gpx_file.bounds.max_lat)
|
22
|
-
assert_equal(-109.447045, gpx_file.bounds.max_lon)
|
23
|
-
assert_equal('description of my GPX file with special char like &, <, >', gpx_file.description)
|
24
|
-
assert_equal('description of my GPX file with special char like &, <, >', gpx_file.description)
|
25
|
-
assert_equal(3.0724966849262554, gpx_file.distance)
|
26
|
-
assert_equal(15_237.0, gpx_file.duration)
|
27
|
-
assert_equal(3036.0, gpx_file.moving_duration)
|
28
|
-
assert_equal(3.6432767014935834, gpx_file.average_speed)
|
15
|
+
shared_assertions_for_one_track_file(gpx_file)
|
29
16
|
end
|
30
17
|
|
31
18
|
def test_load_data_from_file
|
32
19
|
gpx_file = GPX::GPXFile.new(gpx_file: ONE_TRACK_FILE)
|
33
|
-
|
34
|
-
assert_equal(8, gpx_file.tracks.first.segments.size)
|
35
|
-
assert_equal('ACTIVE LOG', gpx_file.tracks.first.name)
|
36
|
-
assert_equal('active_log.gpx', gpx_file.name)
|
37
|
-
assert_equal('2006-04-08T16:44:28Z', gpx_file.time.xmlschema)
|
38
|
-
assert_equal(38.681488, gpx_file.bounds.min_lat)
|
39
|
-
assert_equal(-109.606948, gpx_file.bounds.min_lon)
|
40
|
-
assert_equal(38.791759, gpx_file.bounds.max_lat)
|
41
|
-
assert_equal(-109.447045, gpx_file.bounds.max_lon)
|
42
|
-
assert_equal('description of my GPX file with special char like &, <, >', gpx_file.description)
|
43
|
-
assert_equal(3.0724966849262554, gpx_file.distance)
|
44
|
-
assert_equal(15_237.0, gpx_file.duration)
|
45
|
-
assert_equal(3036.0, gpx_file.moving_duration)
|
46
|
-
assert_equal(3.6432767014935834, gpx_file.average_speed)
|
20
|
+
shared_assertions_for_one_track_file(gpx_file)
|
47
21
|
end
|
48
22
|
|
49
23
|
def test_big_file
|
@@ -74,4 +48,35 @@ class GPXFileTest < Minitest::Test
|
|
74
48
|
assert_equal(21.0, gpx_file.moving_duration)
|
75
49
|
assert_equal(6.674040636626879, gpx_file.average_speed)
|
76
50
|
end
|
51
|
+
|
52
|
+
def test_load_data_from_stringio_assigned_gpx_file
|
53
|
+
str = File.open(ONE_TRACK_FILE).read
|
54
|
+
io = StringIO.new(str, 'r+')
|
55
|
+
gpx_file = GPX::GPXFile.new(gpx_file: io)
|
56
|
+
shared_assertions_for_one_track_file(gpx_file)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_load_data_from_stringio_assigned_gpx_data
|
60
|
+
str = File.open(ONE_TRACK_FILE).read
|
61
|
+
io = StringIO.new(str, 'r+')
|
62
|
+
gpx_file = GPX::GPXFile.new(gpx_data: io)
|
63
|
+
shared_assertions_for_one_track_file(gpx_file)
|
64
|
+
end
|
65
|
+
|
66
|
+
def shared_assertions_for_one_track_file(gpx_file)
|
67
|
+
assert_equal(1, gpx_file.tracks.size)
|
68
|
+
assert_equal(8, gpx_file.tracks.first.segments.size)
|
69
|
+
assert_equal('ACTIVE LOG', gpx_file.tracks.first.name)
|
70
|
+
assert_equal('active_log.gpx', gpx_file.name)
|
71
|
+
assert_equal('2006-04-08T16:44:28Z', gpx_file.time.xmlschema)
|
72
|
+
assert_equal(38.681488, gpx_file.bounds.min_lat)
|
73
|
+
assert_equal(-109.606948, gpx_file.bounds.min_lon)
|
74
|
+
assert_equal(38.791759, gpx_file.bounds.max_lat)
|
75
|
+
assert_equal(-109.447045, gpx_file.bounds.max_lon)
|
76
|
+
assert_equal('description of my GPX file with special char like &, <, >', gpx_file.description)
|
77
|
+
assert_equal(3.0724966849262554, gpx_file.distance)
|
78
|
+
assert_equal(15_237.0, gpx_file.duration)
|
79
|
+
assert_equal(3036.0, gpx_file.moving_duration)
|
80
|
+
assert_equal(3.6432767014935834, gpx_file.average_speed)
|
81
|
+
end
|
77
82
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gpx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Dott
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-07-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -93,14 +93,17 @@ extra_rdoc_files: []
|
|
93
93
|
files:
|
94
94
|
- ".github/workflows/ruby.yml"
|
95
95
|
- ".gitignore"
|
96
|
+
- ".rubocop"
|
96
97
|
- ".rubocop.yml"
|
97
98
|
- ".ruby-version"
|
99
|
+
- ".tool-versions"
|
98
100
|
- ".travis.yml"
|
99
101
|
- CHANGELOG.md
|
100
102
|
- Gemfile
|
101
103
|
- LICENSE.txt
|
102
104
|
- README.md
|
103
105
|
- Rakefile
|
106
|
+
- UPGRADING.md
|
104
107
|
- bin/gpx_distance
|
105
108
|
- bin/gpx_smooth
|
106
109
|
- gpx.gemspec
|
@@ -158,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
158
161
|
requirements:
|
159
162
|
- - ">="
|
160
163
|
- !ruby/object:Gem::Version
|
161
|
-
version: '2.
|
164
|
+
version: '2.7'
|
162
165
|
- - "<"
|
163
166
|
- !ruby/object:Gem::Version
|
164
167
|
version: '4'
|
@@ -168,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
171
|
- !ruby/object:Gem::Version
|
169
172
|
version: '0'
|
170
173
|
requirements: []
|
171
|
-
rubygems_version: 3.
|
174
|
+
rubygems_version: 3.4.10
|
172
175
|
signing_key:
|
173
176
|
specification_version: 4
|
174
177
|
summary: A basic API for reading and writing GPX files.
|