gpx_reader 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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>