gpx_track 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +7 -0
- data/gpx.gemspec +27 -0
- data/lib/gpx/exceptions.rb +7 -0
- data/lib/gpx/geopoint.rb +12 -0
- data/lib/gpx/gpx.rb +121 -0
- data/lib/gpx/haversine.rb +32 -0
- data/lib/gpx/version.rb +3 -0
- data/lib/gpx.rb +9 -0
- data/spec/assets/blank.gif +0 -0
- data/spec/assets/blank.gpx +0 -0
- data/spec/assets/empty.gpx +10 -0
- data/spec/assets/one_point.gpx +19 -0
- data/spec/assets/two_tracks.gpx +48 -0
- data/spec/lib/geopoint_spec.rb +19 -0
- data/spec/lib/gpx_spec.rb +185 -0
- data/spec/lib/haversine_spec.rb +53 -0
- data/spec/spec_helper.rb +4 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa9f853406843a0cde03333879fbf1af4572cbe5
|
4
|
+
data.tar.gz: a2015d8bafd5bb029f6af731657ad5274112c3f7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d772909f9896f1ba4a24ba0df340d59c1816a3cb9bd42a00423f2cc5aa9f9665dc68b8cb9fffa5f79644365f35fbe1a0a0244c2b5f8578c060777f637e2d9a5
|
7
|
+
data.tar.gz: 0008564066046f99ee8f0e23f98e904cae286b76f0bb9d8088fb4c914eedc52cdad119680b24803e1cb99b2df25e075f21cb47fce82a84db42ae9552142681e4
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gpx
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0-p247
|
data/.simplecov
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dawid Dziurdzia
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# GPX gem
|
2
|
+
|
3
|
+
Gem that helps parsing and calculating stats form GPX files.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'gpx'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install gpx
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
require 'gpx'
|
24
|
+
|
25
|
+
gpx = GPX.new 'path_to_GPX_file'
|
26
|
+
|
27
|
+
gpx.points_count # get count of track points
|
28
|
+
|
29
|
+
gpx.times.last[:t] # get track length
|
30
|
+
gpx.times[n][:dt] # get time delta for n-th and n-1-th track point
|
31
|
+
|
32
|
+
gpx.distance[n][:s] # get distance between track start and n-th track point
|
33
|
+
gpx.distance[n][:ds] # get distance delta for track n-th and n-1-th track point
|
34
|
+
|
35
|
+
gpx.max_speed # get max value from all partial speeds (ds/dt)
|
36
|
+
gpx.average_speed # get average speed for track
|
37
|
+
|
38
|
+
gpx.speeds # get partial speeds
|
39
|
+
|
40
|
+
gpx.start_date # date when track begins
|
41
|
+
gpx.end_date # date when track ends
|
42
|
+
|
43
|
+
## Contributing
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/gpx.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gpx/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gpx_track"
|
8
|
+
spec.version = GPX::VERSION
|
9
|
+
spec.authors = ["Dawid Dziurdzia"]
|
10
|
+
spec.email = ["ddziurdzia@me.com"]
|
11
|
+
spec.description = %q{Provide GPX file parsing}
|
12
|
+
spec.summary = %q{Provide GPX file parsing}
|
13
|
+
spec.homepage = "http://cycloo.pl"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "simplecov"
|
25
|
+
|
26
|
+
spec.add_dependency "nokogiri"
|
27
|
+
end
|
data/lib/gpx/geopoint.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module GPX
|
2
|
+
# Class holds coordinates and elevation of single point
|
3
|
+
class GeoPoint
|
4
|
+
attr_accessor :latitude, :longitude, :elevation
|
5
|
+
|
6
|
+
def initialize(latitude: latitude, longitude:longitude, elevation:elevation)
|
7
|
+
self.latitude = latitude
|
8
|
+
self.longitude = longitude
|
9
|
+
self.elevation = elevation
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/gpx/gpx.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module GPX
|
5
|
+
|
6
|
+
# Class is responsible for parsing GPX files and calculate track statistics
|
7
|
+
class GPX
|
8
|
+
attr_reader :points_count,
|
9
|
+
:points,
|
10
|
+
:times,
|
11
|
+
:speeds,
|
12
|
+
:distances,
|
13
|
+
:average_speed,
|
14
|
+
:max_speed,
|
15
|
+
:start_date,
|
16
|
+
:end_date
|
17
|
+
|
18
|
+
def points_count
|
19
|
+
(@points) ? @points.count : 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_date
|
23
|
+
@dates.first
|
24
|
+
end
|
25
|
+
|
26
|
+
def end_date
|
27
|
+
@dates.last
|
28
|
+
end
|
29
|
+
|
30
|
+
def speeds
|
31
|
+
unless @speeds
|
32
|
+
@speeds = self.distances.zip(self.times).collect do |dist,time|
|
33
|
+
dt = time[:dt]
|
34
|
+
unless dt == 0
|
35
|
+
next dist[:ds]/dt*3600
|
36
|
+
else
|
37
|
+
next 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@speeds
|
42
|
+
end
|
43
|
+
|
44
|
+
def max_speed
|
45
|
+
unless @max_speed
|
46
|
+
@max_speed = self.speeds.sort_by{|speed| speed}.last
|
47
|
+
end
|
48
|
+
@max_speed
|
49
|
+
end
|
50
|
+
|
51
|
+
def average_speed
|
52
|
+
unless @average_speed
|
53
|
+
@average_speed = 0
|
54
|
+
total_time = self.times.last[:t]
|
55
|
+
@average_speed = self.distances.last[:s] / total_time * 3600 unless total_time==0
|
56
|
+
end
|
57
|
+
@average_speed
|
58
|
+
end
|
59
|
+
|
60
|
+
def times
|
61
|
+
calculate_times unless @times
|
62
|
+
@times
|
63
|
+
end
|
64
|
+
|
65
|
+
def distances
|
66
|
+
calculate_distances unless @distances
|
67
|
+
@distances
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize(path)
|
71
|
+
@doc = nil
|
72
|
+
|
73
|
+
begin
|
74
|
+
path = open(path)
|
75
|
+
doc = Nokogiri::XML(path)
|
76
|
+
rescue
|
77
|
+
raise GPXInvalidFileException
|
78
|
+
end
|
79
|
+
|
80
|
+
# raise GPXInvalidFileException if doc.children.empty?
|
81
|
+
|
82
|
+
@points = []
|
83
|
+
@dates = []
|
84
|
+
|
85
|
+
doc.search('trkpt').map do |el|
|
86
|
+
@dates.push Time.parse(el.at('time').text)
|
87
|
+
@points.push GeoPoint.new(
|
88
|
+
latitude: el['lat'].to_f,
|
89
|
+
longitude: el['lon'].to_f,
|
90
|
+
elevation: el.at('ele').text.to_f
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def calculate_times
|
98
|
+
@times = [ { dt: 0.0, t: 0.0 } ]
|
99
|
+
@dates.each_cons(2) do |date|
|
100
|
+
time = {
|
101
|
+
dt: difference = date[1] - date[0],
|
102
|
+
t: difference + @times.last[:t]
|
103
|
+
}
|
104
|
+
@times.push time
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def calculate_distances
|
109
|
+
@distances = [ {ds: 0.0, s: 0.0} ]
|
110
|
+
@points.each_cons(2) do |point|
|
111
|
+
distance = {
|
112
|
+
ds: difference = Haversine.distance(point[0], point[1]),
|
113
|
+
s: difference + @distances.last[:s]
|
114
|
+
}
|
115
|
+
@distances.push distance
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GPX
|
2
|
+
|
3
|
+
# Class is responsible for calculating distance between two geo points (it considers point height)
|
4
|
+
class Haversine
|
5
|
+
RADIAN_PER_DEGREE = Math::PI/180.0
|
6
|
+
EARTH_RADIUS = 6371.00079
|
7
|
+
|
8
|
+
def self.distance(first_point, second_point)
|
9
|
+
first_latitude_rad = first_point.latitude.to_f * RADIAN_PER_DEGREE
|
10
|
+
second_latitude_rad = second_point.latitude.to_f * RADIAN_PER_DEGREE
|
11
|
+
|
12
|
+
delta_longitude = (second_point.longitude.to_f - first_point.longitude.to_f) * RADIAN_PER_DEGREE
|
13
|
+
delta_latitude = (second_point.latitude.to_f - first_point.latitude.to_f) * RADIAN_PER_DEGREE
|
14
|
+
|
15
|
+
elevation = (first_point.elevation.to_f / 1000.0 - second_point.elevation.to_f / 1000.0).abs
|
16
|
+
|
17
|
+
triangulate(EARTH_RADIUS * calculate_distance(first_latitude_rad, second_latitude_rad, delta_latitude, delta_longitude), elevation)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def self.calculate_distance(first_latitude_rad, second_latitude_rad, delta_latitude, delta_longitude)
|
22
|
+
coefficient = (Math::sin(delta_latitude/2.0)**2.0) +
|
23
|
+
Math::cos(first_latitude_rad) * Math::cos(second_latitude_rad) * (Math::sin(delta_longitude/2.0)**2.0)
|
24
|
+
|
25
|
+
2.0 * Math::atan2(Math::sqrt(coefficient), Math::sqrt(1.0-coefficient))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.triangulate (distance, height)
|
29
|
+
Math::sqrt(distance**2 + height**2)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/gpx/version.rb
ADDED
data/lib/gpx.rb
ADDED
Binary file
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
2
|
+
|
3
|
+
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
|
4
|
+
<metadata>
|
5
|
+
<link href="http://www.garmin.com">
|
6
|
+
<text>Garmin International</text>
|
7
|
+
</link>
|
8
|
+
<time>2009-10-17T22:58:43Z</time>
|
9
|
+
</metadata>
|
10
|
+
</gpx>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
2
|
+
|
3
|
+
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
|
4
|
+
<metadata>
|
5
|
+
<link href="http://www.garmin.com">
|
6
|
+
<text>Garmin International</text>
|
7
|
+
</link>
|
8
|
+
<time>2009-10-17T22:58:43Z</time>
|
9
|
+
</metadata>
|
10
|
+
<trk>
|
11
|
+
<name>Example GPX Document</name>
|
12
|
+
<trkseg>
|
13
|
+
<trkpt lat="47.644548" lon="-122.326897">
|
14
|
+
<ele>4.46</ele>
|
15
|
+
<time>2009-10-17T18:37:26Z</time>
|
16
|
+
</trkpt>
|
17
|
+
</trkseg>
|
18
|
+
</trk>
|
19
|
+
</gpx>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
2
|
+
|
3
|
+
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
|
4
|
+
<metadata>
|
5
|
+
<link href="http://www.garmin.com">
|
6
|
+
<text>Garmin International</text>
|
7
|
+
</link>
|
8
|
+
<time>2009-10-17T22:58:43Z</time>
|
9
|
+
</metadata>
|
10
|
+
<trk>
|
11
|
+
<name>Example GPX Document</name>
|
12
|
+
<trkseg>
|
13
|
+
<trkpt lat="47.644548" lon="-122.326897">
|
14
|
+
<ele>4.46</ele>
|
15
|
+
<time>2009-10-17T18:37:26Z</time>
|
16
|
+
</trkpt>
|
17
|
+
</trkseg>
|
18
|
+
<trkseg>
|
19
|
+
<trkpt lat="47.644549" lon="-122.326887">
|
20
|
+
<ele>4.46</ele>
|
21
|
+
<time>2009-10-17T18:37:27Z</time>
|
22
|
+
</trkpt>
|
23
|
+
<trkpt lat="47.64456" lon="-122.326867">
|
24
|
+
<ele>4.46</ele>
|
25
|
+
<time>2009-10-17T18:37:28Z</time>
|
26
|
+
</trkpt>
|
27
|
+
</trkseg>
|
28
|
+
</trk>
|
29
|
+
<trk>
|
30
|
+
<name>Example GPX Document</name>
|
31
|
+
<trkseg>
|
32
|
+
<trkpt lat="47.644548" lon="-122.326897">
|
33
|
+
<ele>4.46</ele>
|
34
|
+
<time>2009-10-17T18:38:26Z</time>
|
35
|
+
</trkpt>
|
36
|
+
</trkseg>
|
37
|
+
<trkseg>
|
38
|
+
<trkpt lat="47.644549" lon="-122.326887">
|
39
|
+
<ele>4.46</ele>
|
40
|
+
<time>2009-10-17T18:38:27Z</time>
|
41
|
+
</trkpt>
|
42
|
+
<trkpt lat="47.64456" lon="-122.326867">
|
43
|
+
<ele>4.46</ele>
|
44
|
+
<time>2009-10-17T18:38:29Z</time>
|
45
|
+
</trkpt>
|
46
|
+
</trkseg>
|
47
|
+
</trk>
|
48
|
+
</gpx>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GPX::GeoPoint do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@geopoint = GPX::GeoPoint.new(latitude: 0, longitude: 0, elevation: 0)
|
7
|
+
end
|
8
|
+
|
9
|
+
subject { @geopoint }
|
10
|
+
|
11
|
+
it { should respond_to :latitude }
|
12
|
+
it { should respond_to :latitude= }
|
13
|
+
|
14
|
+
it { should respond_to :longitude }
|
15
|
+
it { should respond_to :longitude= }
|
16
|
+
|
17
|
+
it { should respond_to :elevation }
|
18
|
+
it { should respond_to :elevation= }
|
19
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GPX do
|
4
|
+
|
5
|
+
describe "file with one point" do
|
6
|
+
before do
|
7
|
+
@gpx = GPX::GPX.new 'spec/assets/one_point.gpx'
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { @gpx }
|
11
|
+
|
12
|
+
it { should respond_to :points }
|
13
|
+
it { should_not respond_to :points= }
|
14
|
+
|
15
|
+
it { should respond_to :points_count }
|
16
|
+
it { should_not respond_to :points_count= }
|
17
|
+
|
18
|
+
it { should_not respond_to :elevations }
|
19
|
+
it { should_not respond_to :elevations= }
|
20
|
+
|
21
|
+
it { should respond_to :times }
|
22
|
+
it { should_not respond_to :times= }
|
23
|
+
|
24
|
+
it { should respond_to :speeds }
|
25
|
+
it { should_not respond_to :speeds= }
|
26
|
+
|
27
|
+
it { should respond_to :distances }
|
28
|
+
it { should_not respond_to :distances= }
|
29
|
+
|
30
|
+
it { should_not respond_to :times_cumulated }
|
31
|
+
it { should_not respond_to :times_cumulated= }
|
32
|
+
|
33
|
+
it { should_not respond_to :distances_cumulated }
|
34
|
+
it { should_not respond_to :distances_cumulated= }
|
35
|
+
|
36
|
+
it { should respond_to :average_speed }
|
37
|
+
it { should_not respond_to :average_speed= }
|
38
|
+
|
39
|
+
it { should respond_to :max_speed }
|
40
|
+
it { should_not respond_to :max_speed= }
|
41
|
+
|
42
|
+
it { should respond_to :start_date }
|
43
|
+
it { should_not respond_to :start_date= }
|
44
|
+
|
45
|
+
it { should respond_to :end_date }
|
46
|
+
it { should_not respond_to :end_date= }
|
47
|
+
|
48
|
+
it "should return one point" do
|
49
|
+
@gpx.points_count.should eq 1
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return point time" do
|
53
|
+
@gpx.times.first[:dt].should eq 0
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return point cumulated time" do
|
57
|
+
@gpx.times.first[:t].should eq 0
|
58
|
+
end
|
59
|
+
|
60
|
+
it "average speed should be zero" do
|
61
|
+
@gpx.average_speed.should eq 0
|
62
|
+
end
|
63
|
+
|
64
|
+
it "max speed should be zero" do
|
65
|
+
@gpx.max_speed.should eq 0
|
66
|
+
end
|
67
|
+
|
68
|
+
it "start date should not be nil" do
|
69
|
+
@gpx.start_date.should_not eq nil
|
70
|
+
end
|
71
|
+
|
72
|
+
it "start date should equals end date" do
|
73
|
+
@gpx.start_date.should eq @gpx.end_date
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "should return one zero distance (because of one point)" do
|
77
|
+
it "distances count should equals one" do
|
78
|
+
@gpx.distances.count.should eq 1
|
79
|
+
end
|
80
|
+
it "first distance should be zero" do
|
81
|
+
@gpx.distances.first[:ds].should eq 0
|
82
|
+
end
|
83
|
+
it "first cumulated distance should be zero" do
|
84
|
+
@gpx.distances.first[:s].should eq 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "should return one zero speed (because of one point)" do
|
89
|
+
it "speeds count should equals one" do
|
90
|
+
@gpx.speeds.count.should eq 1
|
91
|
+
end
|
92
|
+
it "first speed should be zero" do
|
93
|
+
@gpx.speeds[0].should eq 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should have proper latitude" do
|
98
|
+
@gpx.points.first.latitude.should eq 47.644548
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "file with more than one track point" do
|
103
|
+
POINTS_COUNT = 6
|
104
|
+
|
105
|
+
before do
|
106
|
+
@gpx = GPX::GPX.new 'spec/assets/two_tracks.gpx'
|
107
|
+
end
|
108
|
+
|
109
|
+
subject { @gpx }
|
110
|
+
|
111
|
+
it "should return all points in one array" do
|
112
|
+
@gpx.points_count.should eq POINTS_COUNT
|
113
|
+
end
|
114
|
+
|
115
|
+
it "last point should not be nil" do
|
116
|
+
@gpx.points.last.should_not eq nil
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should return same count of distances elements as points" do
|
120
|
+
@gpx.distances.count.should eq POINTS_COUNT
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should return same count of speeds elements as points" do
|
124
|
+
@gpx.speeds.count.should eq POINTS_COUNT
|
125
|
+
end
|
126
|
+
|
127
|
+
it "last point speed should not be nil" do
|
128
|
+
@gpx.speeds.last.should_not eq nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should return same count of time elements as points" do
|
132
|
+
@gpx.times.count.should eq POINTS_COUNT
|
133
|
+
end
|
134
|
+
|
135
|
+
it "last point time should not be nil" do
|
136
|
+
@gpx.times.last.should_not eq nil
|
137
|
+
end
|
138
|
+
|
139
|
+
it "last point cumulated time should be positive" do
|
140
|
+
@gpx.times.last[:t].should > 0
|
141
|
+
end
|
142
|
+
|
143
|
+
it "last point distance should not be zero" do
|
144
|
+
@gpx.distances.last[:ds].should_not eq 0
|
145
|
+
end
|
146
|
+
|
147
|
+
it "last point cumulated distance should not be zero" do
|
148
|
+
@gpx.distances.last[:s].should_not eq 0
|
149
|
+
end
|
150
|
+
|
151
|
+
it "average speed should be positive" do
|
152
|
+
@gpx.average_speed.should > 0
|
153
|
+
end
|
154
|
+
|
155
|
+
it "max speed should be positive" do
|
156
|
+
@gpx.max_speed.should > 0
|
157
|
+
end
|
158
|
+
|
159
|
+
it "start date should not equals end date" do
|
160
|
+
@gpx.start_date.should_not eq @gpx.end_date
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it "return exeption for non-existing file" do
|
165
|
+
expect {
|
166
|
+
gpx = GPX::GPX.new 'spec/assets/some_filt_that_not_exists_25363.gpx'
|
167
|
+
}.to raise_error( GPX::GPXInvalidFileException )
|
168
|
+
end
|
169
|
+
|
170
|
+
let(:wrong_file_type_gpx) {GPX::GPX.new 'spec/assets/blank.gif'}
|
171
|
+
it "return no points for wrong file type" do
|
172
|
+
wrong_file_type_gpx.points_count.should eq 0
|
173
|
+
end
|
174
|
+
|
175
|
+
let(:blank_file_gpx) {GPX::GPX.new 'spec/assets/blank.gpx'}
|
176
|
+
it "return no points for blank file" do
|
177
|
+
blank_file_gpx.points_count.should eq 0
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return zero points for file with no track point" do
|
181
|
+
gpx = GPX::GPX.new 'spec/assets/empty.gpx'
|
182
|
+
gpx.points_count.should eq(0)
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
PRECISION = 0.002 # 0.01%
|
4
|
+
|
5
|
+
describe GPX::Haversine do
|
6
|
+
def should_equals_distance_with_precision(checked_distance, real_distance)
|
7
|
+
(checked_distance-real_distance).abs.should < real_distance * PRECISION
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:zabrze) { GPX::GeoPoint.new(latitude: 50.3167, longitude: 18.7833, elevation: 0) }
|
11
|
+
let(:katowice) { GPX::GeoPoint.new(latitude: 50.2667, longitude: 19.0167, elevation: 0) }
|
12
|
+
let(:katowice_distance) { 17.47 }
|
13
|
+
|
14
|
+
it "should return proper distance from Zabrze, PL to Katowice, PL" do
|
15
|
+
distance = GPX::Haversine.distance(zabrze, katowice)
|
16
|
+
should_equals_distance_with_precision(distance, katowice_distance)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return proper distance from Katowice, PL to Zabrze, PL" do
|
20
|
+
distance = GPX::Haversine.distance(katowice, zabrze)
|
21
|
+
should_equals_distance_with_precision(distance, katowice_distance)
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:tokyo) { GPX::GeoPoint.new(latitude: 35.6850, longitude: 139.7514, elevation: 0) }
|
25
|
+
let(:london) { GPX::GeoPoint.new(latitude: 51.5000, longitude: -0.1167, elevation: 0) }
|
26
|
+
let(:london_distance) { 9554.72 }
|
27
|
+
|
28
|
+
it "should return proper distance from Tokyo, JP to London, GB" do
|
29
|
+
distance = GPX::Haversine.distance(tokyo, london)
|
30
|
+
should_equals_distance_with_precision(distance, london_distance)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return proper length of half of equinox" do
|
34
|
+
distance = GPX::Haversine.distance(
|
35
|
+
GPX::GeoPoint.new(latitude: 0, longitude: 0, elevation: 0),
|
36
|
+
GPX::GeoPoint.new(longitude: 0, longitude: 180, elevation: 0)
|
37
|
+
)
|
38
|
+
should_equals_distance_with_precision(distance, 20038)
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:same_point) { GPX::GeoPoint.new(latitude: 44.654, longitude: 44.654, elevation: 0) }
|
42
|
+
it "should return 0 for same lat/lon" do
|
43
|
+
distance = GPX::Haversine.distance(same_point,same_point)
|
44
|
+
distance.should eq 0
|
45
|
+
end
|
46
|
+
|
47
|
+
let(:height) { GPX::GeoPoint.new(latitude: 44.654, longitude: 44.654, elevation: 1233.54) }
|
48
|
+
it "should return proper height for same lat/lon" do
|
49
|
+
distance = GPX::Haversine.distance(same_point, height)
|
50
|
+
distance.should eq height.elevation/1000
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gpx_track
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dawid Dziurdzia
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Provide GPX file parsing
|
84
|
+
email:
|
85
|
+
- ddziurdzia@me.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .ruby-gemset
|
92
|
+
- .ruby-version
|
93
|
+
- .simplecov
|
94
|
+
- Gemfile
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- gpx.gemspec
|
99
|
+
- lib/gpx.rb
|
100
|
+
- lib/gpx/exceptions.rb
|
101
|
+
- lib/gpx/geopoint.rb
|
102
|
+
- lib/gpx/gpx.rb
|
103
|
+
- lib/gpx/haversine.rb
|
104
|
+
- lib/gpx/version.rb
|
105
|
+
- spec/assets/blank.gif
|
106
|
+
- spec/assets/blank.gpx
|
107
|
+
- spec/assets/empty.gpx
|
108
|
+
- spec/assets/one_point.gpx
|
109
|
+
- spec/assets/two_tracks.gpx
|
110
|
+
- spec/lib/geopoint_spec.rb
|
111
|
+
- spec/lib/gpx_spec.rb
|
112
|
+
- spec/lib/haversine_spec.rb
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
homepage: http://cycloo.pl
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.0.5
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Provide GPX file parsing
|
138
|
+
test_files:
|
139
|
+
- spec/assets/blank.gif
|
140
|
+
- spec/assets/blank.gpx
|
141
|
+
- spec/assets/empty.gpx
|
142
|
+
- spec/assets/one_point.gpx
|
143
|
+
- spec/assets/two_tracks.gpx
|
144
|
+
- spec/lib/geopoint_spec.rb
|
145
|
+
- spec/lib/gpx_spec.rb
|
146
|
+
- spec/lib/haversine_spec.rb
|
147
|
+
- spec/spec_helper.rb
|