gpx_reader 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f76bf78f2d9cd33da17c24b1fe7ae0b3e772173
4
+ data.tar.gz: 56a6db69ab36cbf3137989395d2aae479e358fc6
5
+ SHA512:
6
+ metadata.gz: 7eb9cb1f3cf4c4354332c52612191c84521c7d2bdafabe76d180f668065b4a43abb1a01547655da1f62cb3607f8e7970b9e15be598ed3af7a412984213bd9a5c
7
+ data.tar.gz: 86cf40a4f04a1a9387257fdc4f75c5e61a1175b28145fa12f41def2666774bffb69b90ccb577caa89059665be9af0ff6bb00afca5b776b3d1410ff1f070b038d
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gpx_reader.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Nicolas Aguttes
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,56 @@
1
+ # Gpx Reader
2
+
3
+ gem to read a gpx file
4
+
5
+ **ATTENTION**: this version works but is still under (slow) development
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'gpx_reader'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install gpx_reader
20
+
21
+ ## Usage
22
+
23
+ gpx_reader accept a file as argument or a string.
24
+
25
+ To read a gpx file just call @gpx = GPXReader::Gpx.new(file) or @gpx = GPXReader::Gpx.new(string)
26
+
27
+ Then use it as follow:
28
+
29
+ - @gpx.creator => creator of the file
30
+ - @gpx.time => Time of creation
31
+ - @gpx.tracks => array of track
32
+ - for the track inside @gpx.tracks
33
+ - track.name
34
+ - track.desc
35
+ - track.segments
36
+ - ...
37
+
38
+ ## Notes
39
+ The distance is calculated based on the haversine method ( http://en.wikipedia.org/wiki/Haversine_formula) and implementation of the algorithm is based on the following source: http://www.movable-type.co.uk/scripts/latlong.html
40
+
41
+ This gem has been written for my own needs, if you feel something is missing don't hesitate to ask
42
+
43
+
44
+ ## TODO
45
+ - list all the points directly from the track
46
+ - calculate boundaries of the tracks/segments unless in the metadata
47
+ - calculate elapsed time
48
+ - write more tests
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gpx_reader/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gpx_reader"
8
+ spec.version = GpxReader::VERSION
9
+ spec.authors = ["Nicolas Aguttes"]
10
+ spec.email = ["nicolas.aguttes@gmail.com"]
11
+ spec.description = %q{Gem to parse a gpx file or string}
12
+ spec.summary = %q{gpx reader}
13
+ spec.homepage = ""
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_dependency "nokogiri", "1.6.1"
24
+
25
+ end
@@ -0,0 +1,51 @@
1
+ #--
2
+ # Copyright (c) 2014 Nicolas Aguttes
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ module GPXReader
24
+ class Gpx
25
+ attr_accessor :creator, :tracks, :boundaries, :lowest_point, :highest_point, :duration, :version, :time, :name, :namespaces
26
+ # read the file containing the tracks
27
+ # get the different information of the file
28
+ # get the tracks
29
+ def initialize(file)
30
+ if file.is_a?(File)
31
+ @gpx=Nokogiri::XML(File.open(file))
32
+ else
33
+ @gpx=Nokogiri::XML(file)
34
+ end
35
+ @creator = @gpx.at_css("gpx")["creator"] rescue nil
36
+ @time = Time.parse(@gpx.at_css("metadata time").text) rescue nil
37
+ @tracks = []
38
+ @gpx.css("trk").each do |trk|
39
+ trk = Track.new(trk)
40
+ @tracks << trk
41
+ end
42
+ # get name spaces
43
+ ns = @gpx.collect_namespaces
44
+ # Strip the leading xmlns: from each namespace key, and store in a new hash
45
+ @namespaces= {}
46
+ ns.each_pair do |key, value|
47
+ @namespaces[key.sub(/^xmlns:/, '')] = value
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ #--
2
+ # Copyright (c) 2014 Nicolas Aguttes
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ module GPXReader
24
+ class Point
25
+ attr_accessor :lat, :lon, :elevation, :time, :hr
26
+
27
+ def initialize(point)
28
+ @lat = point["lat"].to_f rescue nil
29
+ @lon = point["lon"].to_f rescue nil
30
+ @elevation = point.at_css("ele").text.to_f rescue nil
31
+ @time = Time.parse(point.at_css("time").text) rescue nil
32
+ @hr = point.at_xpath(".//gpxtpx:hr").text.to_i rescue nil
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,61 @@
1
+ #--
2
+ # Copyright (c) 2014 Nicolas Aguttes
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ module GPXReader
24
+ class Segment
25
+ attr_accessor :points, :distance
26
+
27
+ def initialize(segment)
28
+ @distance = 0
29
+ @points = []
30
+ previous_pt = nil
31
+ segment.css("trkpt").each do |pt|
32
+ point = Point.new(pt)
33
+ @points << point
34
+ # calculate distance
35
+ @distance += haversine_distance(previous_pt, point) unless previous_pt.nil?
36
+ previous_pt = point
37
+ # puts @points.size if @points.size.modulo(100).zero?
38
+ end
39
+ end
40
+
41
+ # caluclate the distance between 2 points
42
+ # http://en.wikipedia.org/wiki/Haversine_formula
43
+ # http://www.movable-type.co.uk/scripts/latlong.html
44
+ # the "Earth radius" R varies from 6356.752 km at the poles to 6378.137 km
45
+ # we calculate with the average radius (in km)
46
+ RADIUS = 6371
47
+ # Calculate the Haversine distance between two points
48
+ def haversine_distance(pt1, pt2)
49
+ # lat/lon are in degrees, need to convert in radiant
50
+ # formula ==> Degrees * PI / 180
51
+ d_lat = (pt2.lat - pt1.lat) * Math::PI / 180
52
+ d_lon = (pt2.lon - pt1.lon) * Math::PI / 180
53
+ lat1_r = pt1.lat * Math::PI / 180
54
+ lat2_r = pt2.lat * Math::PI / 180
55
+ a = Math.sin(d_lat/2) * Math.sin(d_lat/2) + Math.cos(lat1_r) * Math.cos(lat2_r) * Math.sin(d_lon/2) * Math.sin(d_lon/2)
56
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
57
+ d = RADIUS * c
58
+ return d
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,39 @@
1
+ #--
2
+ # Copyright (c) 2014 Nicolas Aguttes
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ module GPXReader
24
+ class Track
25
+ attr_accessor :segments, :name, :desc, :distance
26
+
27
+ def initialize(trk)
28
+ @distance = 0
29
+ @name = trk.at_css("name").text rescue ""
30
+ @desc = trk.at_css("desc").text rescue ""
31
+ @segments = []
32
+ trk.css("trkseg").each do |seg|
33
+ seg = Segment.new(seg)
34
+ @segments << seg
35
+ @distance += seg.distance
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module GpxReader
2
+ VERSION = "0.1.0"
3
+ end
data/lib/gpx_reader.rb ADDED
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Copyright (c) 2014 Nicolas Aguttes
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ $:.unshift(File.dirname(__FILE__))
24
+ require "gpx_reader/version"
25
+ require "nokogiri"
26
+
27
+ require 'date'
28
+ require 'time'
29
+ require 'gpx_reader/gpx'
30
+ require 'gpx_reader/track'
31
+ require 'gpx_reader/segment'
32
+ require 'gpx_reader/point'
33
+
data/tests/.DS_Store ADDED
Binary file
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require File.expand_path('../.') + '/gpx_reader/lib/gpx_reader'
3
+
4
+ class GPXFileTest < Test::Unit::TestCase
5
+
6
+ ONE_TRACK_FILE = File.join(File.dirname(__FILE__), "gpx_files/1track_4points.gpx")
7
+
8
+ def test_load_data_from_file
9
+ gpx = GPXReader::Gpx.new(File.open(ONE_TRACK_FILE))
10
+ assert_equal(1, gpx.tracks.size)
11
+ assert_equal(1, gpx.tracks.first.segments.size)
12
+ assert_equal(4, gpx.tracks.first.segments.first.points.size)
13
+ assert_equal("Track One", gpx.tracks.first.name)
14
+ assert_equal("Track One, one segment, 4 points", gpx.tracks.first.desc)
15
+ assert_equal(Time.parse("2014-02-20 08:42:59 UTC"), gpx.time)
16
+ assert_equal(1349, gpx.tracks.first.segments.first.points[0].elevation)
17
+ assert_equal(1350, gpx.tracks.first.segments.first.points[1].elevation)
18
+ assert_equal(1351, gpx.tracks.first.segments.first.points[2].elevation)
19
+ assert_equal(1352, gpx.tracks.first.segments.first.points[3].elevation)
20
+ assert_equal(91, gpx.tracks.first.segments.first.points[0].hr)
21
+ assert_equal(92, gpx.tracks.first.segments.first.points[1].hr)
22
+ assert_equal(93, gpx.tracks.first.segments.first.points[2].hr)
23
+ assert_equal(94, gpx.tracks.first.segments.first.points[3].hr)
24
+ assert_equal(6.934360396116972, gpx.tracks.first.segments.first.points[0].lon)
25
+ assert_equal(6.93439643830061, gpx.tracks.first.segments.first.points[1].lon)
26
+ assert_equal(6.934469779953361, gpx.tracks.first.segments.first.points[2].lon)
27
+ assert_equal(6.934554101899266, gpx.tracks.first.segments.first.points[3].lon)
28
+ assert_equal(46.03442206978798, gpx.tracks.first.segments.first.points[0].lat)
29
+ assert_equal(46.03444067761302, gpx.tracks.first.segments.first.points[1].lat)
30
+ assert_equal(46.03447579778731, gpx.tracks.first.segments.first.points[2].lat)
31
+ assert_equal(46.03450287133455, gpx.tracks.first.segments.first.points[3].lat)
32
+ end
33
+
34
+
35
+ end
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <gpx version="1.1" creator="Garmin Connect"
3
+ 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
+ xmlns="http://www.topografix.com/GPX/1/1"
5
+ xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
6
+ xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
7
+ <metadata>
8
+ <link href="connect.garmin.com">
9
+ <text>Garmin Connect</text>
10
+ </link>
11
+ <time>2014-02-20T08:42:59.000Z</time>
12
+ </metadata>
13
+ <trk>
14
+ <name>Track One</name>
15
+ <desc>Track One, one segment, 4 points</desc>
16
+ <trkseg>
17
+ <trkpt lon="6.934360396116972" lat="46.03442206978798">
18
+ <ele>1349</ele>
19
+ <time>2014-02-20T08:42:59.000Z</time>
20
+ <extensions>
21
+ <gpxtpx:TrackPointExtension>
22
+ <gpxtpx:hr>91</gpxtpx:hr>
23
+ </gpxtpx:TrackPointExtension>
24
+ </extensions>
25
+ </trkpt>
26
+ <trkpt lon="6.93439643830061" lat="46.03444067761302">
27
+ <ele>1350</ele>
28
+ <time>2014-02-20T08:43:00.000Z</time>
29
+ <extensions>
30
+ <gpxtpx:TrackPointExtension>
31
+ <gpxtpx:hr>92</gpxtpx:hr>
32
+ </gpxtpx:TrackPointExtension>
33
+ </extensions>
34
+ </trkpt>
35
+ <trkpt lon="6.934469779953361" lat="46.03447579778731">
36
+ <ele>1351</ele>
37
+ <time>2014-02-20T08:43:02.000Z</time>
38
+ <extensions>
39
+ <gpxtpx:TrackPointExtension>
40
+ <gpxtpx:hr>93</gpxtpx:hr>
41
+ </gpxtpx:TrackPointExtension>
42
+ </extensions>
43
+ </trkpt>
44
+ <trkpt lon="6.934554101899266" lat="46.03450287133455">
45
+ <ele>1352</ele>
46
+ <time>2014-02-20T08:43:05.000Z</time>
47
+ <extensions>
48
+ <gpxtpx:TrackPointExtension>
49
+ <gpxtpx:hr>94</gpxtpx:hr>
50
+ </gpxtpx:TrackPointExtension>
51
+ </extensions>
52
+ </trkpt>
53
+ </trkseg>
54
+ </trk>
55
+ </gpx>