gpx_kml 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.
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gpx_kml/gpx/point'
4
+
5
+ module GPX
6
+
7
+ class Segment
8
+
9
+ def initialize(segment, track)
10
+ return unless segment.is_a?(Nokogiri::XML::Element) && track.is_a?(GPX::Track)
11
+ return if segment.xpath('self::xmlns:trkseg').empty?
12
+
13
+ @points = _points segment
14
+ @track = track
15
+ end
16
+
17
+ attr_reader :track, :points
18
+
19
+ private
20
+
21
+ def _points(segment)
22
+ p = []
23
+ segment.xpath('./xmlns:trkpt').each_with_index do |tp, i|
24
+ p[i] = Point.new(tp, self)
25
+ end
26
+ p
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gpx_kml/gpx/segment'
4
+
5
+ module GPX
6
+ # Docu
7
+ class Track
8
+ def initialize(track)
9
+ return unless track.is_a?(Nokogiri::XML::Element) && !track.xpath('self::xmlns:trk').empty?
10
+
11
+ @name = track.xpath('./xmlns:name/text()').to_s
12
+ @number = track.xpath('./xmlns:number/text()').to_s
13
+ @description = track.xpath('./xmlns:desc/text()').to_s
14
+ @link = track.xpath('./xmlns:link/@href').to_s
15
+ @segments = _segments track
16
+ end
17
+
18
+ attr_reader :segments, :name, :description, :link, :number
19
+
20
+ private
21
+
22
+ def _segments(track)
23
+ track_segment = []
24
+ track.xpath('./xmlns:trkseg').each_with_index do |ts, i|
25
+ track_segment[i] = Segment.new(ts, self)
26
+ end
27
+ track_segment
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'gpx_kml/gpx/track'
5
+ require 'gpx_kml/gpx/route'
6
+ require 'gpx_kml/gpx/point'
7
+
8
+ # Docu
9
+ module GPX
10
+ # Docu
11
+ class Gpx
12
+ def initialize(file_path)
13
+ return unless correct_path?(file_path) && (File.size(file_path) < 10_000_000)
14
+
15
+ @gpx = Nokogiri::XML(File.open(file_path))
16
+ return unless valid?
17
+
18
+ @file_name = File.basename(file_path)
19
+ @name = _name
20
+ @author = @gpx.xpath('/xmlns:gpx/xmlns:metadata/xmlns:author/xmlns:name/text()').to_s
21
+ @link = @gpx.xpath('/xmlns:gpx/xmlns:metadata/xmlns:link/@href').to_s
22
+ @tracks = _tracks if tracks?
23
+ @routes = _routes if routes?
24
+ @points = _points if points?
25
+ @points_length = _points_length
26
+ @routes_length = _routes_length
27
+ @tracks_length = _tracks_length
28
+ end
29
+ # used in development of the gem, could be useful going forward to add functionalities
30
+ # attr_reader :gpx
31
+ attr_reader :tracks, :points, :routes, :name, :file_name, :author, :link
32
+
33
+ # access in readonly to the quantity of points/routes/tracks in the gpx
34
+ attr_reader :points_length, :routes_length, :tracks_length
35
+
36
+ # For a gpx file to be valid it must only have a waypoint, a route or a track
37
+ def valid?
38
+ tracks? || routes? || points?
39
+ end
40
+
41
+ def routes?
42
+ return true unless @gpx.xpath('//xmlns:rte').empty?
43
+
44
+ false
45
+ end
46
+
47
+ def tracks?
48
+ return true unless @gpx.xpath('//xmlns:trk').empty?
49
+
50
+ false
51
+ end
52
+
53
+ def points?
54
+ return true unless @gpx.xpath('//xmlns:wpt').empty?
55
+
56
+ false
57
+ end
58
+
59
+ def _name
60
+ if valid?
61
+ name = @gpx.xpath('/xmlns:gpx/xmlns:metadata/xmlns:name/text()').to_s
62
+ return alt_name if name.empty?
63
+
64
+ return name
65
+ end
66
+ puts 'return empty string'
67
+ ''
68
+ end
69
+
70
+ def description
71
+ return @gpx.xpath('//xmlns:metadata/xmlns:desc/text()').to_s if valid?
72
+
73
+ ''
74
+ end
75
+
76
+ private
77
+
78
+ def _tracks
79
+ t = []
80
+ @gpx.xpath('xmlns:gpx/xmlns:trk').each_with_index do |trk, i|
81
+ t[i] = GPX::Track.new trk
82
+ end
83
+ t
84
+ end
85
+
86
+ def _routes
87
+ r = []
88
+ @gpx.xpath('xmlns:gpx/xmlns:rte').each_with_index do |rte, i|
89
+ r[i] = GPX::Route.new rte
90
+ end
91
+ r
92
+ end
93
+
94
+ def _points
95
+ p = []
96
+ @gpx.xpath('xmlns:gpx/xmlns:wpt').each_with_index do |wpt, i|
97
+ p[i] = GPX::Point.new wpt, self
98
+ end
99
+ p
100
+ end
101
+
102
+ def _tracks_length
103
+ return 0 if @tracks.nil?
104
+
105
+ @tracks.length
106
+ end
107
+
108
+ def _routes_length
109
+ return 0 if @routes.nil?
110
+
111
+ @routes.length
112
+ end
113
+
114
+ def _points_length
115
+ return 0 if @points.nil?
116
+
117
+ @points.length
118
+ end
119
+
120
+ def correct_path?(path)
121
+ return true if path.instance_of?(String) && (path.end_with? '.gpx')
122
+
123
+ false
124
+ end
125
+
126
+ def alt_name
127
+ node = nil
128
+ node = @gpx.xpath('//xmlns:wpt')[0] if points?
129
+ node = @gpx.xpath('//xmlns:trk')[0] if tracks?
130
+ node = @gpx.xpath('//xmlns:rte')[0] if routes?
131
+ return node.xpath('./xmlns:name/text()').to_s unless node.nil?
132
+
133
+ ''
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'gpx_kml/kml'
5
+ require 'gpx_kml/kml/track'
6
+ require 'gpx_kml/kml/route'
7
+
8
+ module KML
9
+ # Docu
10
+ class Point
11
+ def initialize(coord, father, node)
12
+ re = Regexp.new('^ ?[0-9]+\.[0-9]+,[0-9]+\.[0-9]+(,[0-9]+\.[0-9]+)? ?$')
13
+
14
+ return unless valid_father?(father) && re.match?(coord) && node.is_a?(Nokogiri::XML::Element)
15
+ return if node.xpath('self::*[self::xmlns:LineString or self::xmlns:Point or self::xmlns:LinearRing]').empty?
16
+
17
+ @father = father
18
+ coord = coord.split(',')
19
+ @latitude = coord[0]
20
+ @longitude = coord[1]
21
+ @elevation = coord[2] if coord.length == 3
22
+ @node = node
23
+ # Name is looked up in the ancestor of the node that compose this point
24
+ @name = _name
25
+ return if node.xpath('self::xmlns:Point').empty?
26
+
27
+ @author = _author
28
+ @link = _link
29
+ end
30
+
31
+ attr_reader :latitude, :longitude, :elevation, :name, :father, :link, :author
32
+
33
+ private
34
+
35
+ def _name
36
+ elem = @node.xpath('.')
37
+ while elem.xpath('self::xmlns:kml').empty?
38
+ return elem.xpath('./xmlns:name/text()').to_s unless elem.xpath('./xmlns:name').empty?
39
+
40
+ elem = elem.xpath('..')
41
+ end
42
+ ''
43
+ end
44
+
45
+ def _author
46
+ elem = @node.xpath('.')
47
+ while elem.xpath('self::xmlns:kml').empty?
48
+ elem = elem.xpath('..')
49
+ return elem.xpath('./atom:author/atom:name/text()').to_s unless elem.xpath('./atom:author').empty?
50
+ end
51
+ ''
52
+ end
53
+
54
+ def _link
55
+ elem = @node.xpath('.')
56
+ while elem.xpath('self::xmlns:kml').empty?
57
+ elem = elem.xpath('..')
58
+ return elem.xpath('./atom:link/@href').to_s unless elem.xpath('./atom:link').empty?
59
+ end
60
+ ''
61
+ end
62
+
63
+ def valid_father?(father)
64
+ father.is_a?(KML::Track) || father.is_a?(KML::Kml) || father.is_a?(KML::Route)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,55 @@
1
+ module KML
2
+ # Docu
3
+ class Route
4
+ def initialize(route)
5
+ return unless route.is_a?(Nokogiri::XML::Element) && !route.xpath('self::xmlns:LinearRing').empty?
6
+
7
+ @node = route
8
+ @name = _name
9
+ @points = _points
10
+ @author = _author
11
+ @link = _link
12
+ end
13
+
14
+ attr_reader :name, :points, :author, :link
15
+
16
+ private
17
+
18
+ def _name
19
+ elem = @node.xpath('.')
20
+ while elem.xpath('self::xmlns:kml').empty?
21
+ elem = elem.xpath('..')
22
+ return elem.xpath('./xmlns:name/text()').to_s unless elem.xpath('./xmlns:name').empty?
23
+ end
24
+ ''
25
+ end
26
+
27
+ def _points
28
+ p = []
29
+ points = @node.xpath('./xmlns:coordinates/text()').to_s
30
+ array_points = points.split(' ')
31
+ array_points.each_with_index do |ap, i|
32
+ p[i] = KML::Point.new ap, self, @node
33
+ end
34
+ p
35
+ end
36
+
37
+ def _author
38
+ elem = @node.xpath('.')
39
+ while elem.xpath('self::xmlns:kml').empty?
40
+ elem = elem.xpath('..')
41
+ return elem.xpath('./atom:author/atom:name/text()').to_s unless elem.xpath('./atom:author').empty?
42
+ end
43
+ ''
44
+ end
45
+
46
+ def _link
47
+ elem = @node.xpath('.')
48
+ while elem.xpath('self::xmlns:kml').empty?
49
+ elem = elem.xpath('..')
50
+ return elem.xpath('./atom:link/@href').to_s unless elem.xpath('./atom:link').empty?
51
+ end
52
+ ''
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,55 @@
1
+ module KML
2
+ # Docu
3
+ class Track
4
+ def initialize(track)
5
+ return unless track.is_a?(Nokogiri::XML::Element) && !track.xpath('self::xmlns:LineString').empty?
6
+
7
+ @node = track
8
+ @name = _name
9
+ @points = _points
10
+ @author = _author
11
+ @link = _link
12
+ end
13
+
14
+ attr_reader :name, :points, :author, :link
15
+
16
+ private
17
+
18
+ def _name
19
+ elem = @node.xpath('.')
20
+ while elem.xpath('self::xmlns:kml').empty?
21
+ elem = elem.xpath('..')
22
+ return elem.xpath('./xmlns:name/text()').to_s unless elem.xpath('./xmlns:name').empty?
23
+ end
24
+ ''
25
+ end
26
+
27
+ def _points
28
+ p = []
29
+ points = @node.xpath('./xmlns:coordinates/text()').to_s
30
+ array_points = points.split(' ')
31
+ array_points.each_with_index do |ap, i|
32
+ p[i] = KML::Point.new ap, self, @node
33
+ end
34
+ p
35
+ end
36
+
37
+ def _author
38
+ elem = @node.xpath('.')
39
+ while elem.xpath('self::xmlns:kml').empty?
40
+ elem = elem.xpath('..')
41
+ return elem.xpath('./atom:author/atom:name/text()').to_s unless elem.xpath('./atom:author').empty?
42
+ end
43
+ ''
44
+ end
45
+
46
+ def _link
47
+ elem = @node.xpath('.')
48
+ while elem.xpath('self::xmlns:kml').empty?
49
+ elem = elem.xpath('..')
50
+ return elem.xpath('./atom:link/@href').to_s unless elem.xpath('./atom:link').empty?
51
+ end
52
+ ''
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'gpx_kml/kml/point'
5
+ require 'gpx_kml/kml/track'
6
+ require 'gpx_kml/kml/route'
7
+
8
+ module KML
9
+ # Docu
10
+ class Kml
11
+ def initialize(file_path)
12
+ return unless correct_path?(file_path) && (File.size(file_path) < 10_000_000)
13
+
14
+ @kml = Nokogiri::XML(File.open(file_path))
15
+ return unless valid?
16
+
17
+ @file_name = File.basename(file_path)
18
+ @tracks = _tracks
19
+ @routes = _routes
20
+ @points = _points
21
+ @points_length = _points_length
22
+ @routes_length = _routes_length
23
+ @tracks_length = _tracks_length
24
+ end
25
+
26
+ # access in read only of the number of points, routes and tracks in the kml
27
+ attr_reader :points_length, :routes_length, :tracks_length, :file_name
28
+
29
+ # access data of the kml in readonly
30
+ attr_reader :points, :routes, :tracks
31
+
32
+ def valid?
33
+ tracks? || routes? || points?
34
+ end
35
+
36
+ def routes?
37
+ return true unless @kml.xpath('//xmlns:LinearRing').empty?
38
+
39
+ false
40
+ end
41
+
42
+ def tracks?
43
+ return true unless @kml.xpath('//xmlns:LineString').empty?
44
+
45
+ false
46
+ end
47
+
48
+ def points?
49
+ return true unless @kml.xpath('//xmlns:Point').empty?
50
+
51
+ false
52
+ end
53
+
54
+ private
55
+
56
+ def correct_path?(path)
57
+ return true if path.instance_of?(String) && (path.end_with? '.kml')
58
+
59
+ false
60
+ end
61
+
62
+ def _tracks
63
+ t = []
64
+ @kml.xpath('//xmlns:LineString').each_with_index do |ls, i|
65
+ t[i] = KML::Track.new ls
66
+ end
67
+ t
68
+ end
69
+
70
+ def _routes
71
+ r = []
72
+ @kml.xpath('//xmlns:LinearRing').each_with_index do |lr, i|
73
+ r[i] = KML::Route.new lr
74
+ end
75
+ r
76
+ end
77
+
78
+ def _points
79
+ p = []
80
+ @kml.xpath('//xmlns:Point').each_with_index do |pt, i|
81
+ p[i] = KML::Point.new pt.xpath('./xmlns:coordinates/text()').to_s, self, pt
82
+ end
83
+ p
84
+ end
85
+
86
+ def _tracks_length
87
+ return 0 if @tracks.nil?
88
+
89
+ @tracks.length
90
+ end
91
+
92
+ def _routes_length
93
+ return 0 if @routes.nil?
94
+
95
+ @routes.length
96
+ end
97
+
98
+ def _points_length
99
+ return 0 if @points.nil?
100
+
101
+ @points.length
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,8 @@
1
+ <rte>
2
+ <name></name>
3
+ <desc></desc>
4
+ <link href=""></link>
5
+ <number></number>
6
+ <type></type>
7
+ <rtept></rtept>
8
+ </rte>
@@ -0,0 +1,6 @@
1
+ <gpx version="1.1" creator="https://www.github.com/engim-eu/gpx_kml">!
2
+ <metadata>
3
+
4
+ </metadata>
5
+
6
+ </gpx>
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:atom="http://www.w3.org/Atom">
3
+ <Document id="ID">
4
+ <name></name>
5
+ <visibility>1</visibility>
6
+ <open>0</open>
7
+ <atom:author>
8
+ <atom:name></atom:name>!
9
+ <atom:uri></atom:uri>
10
+ <atom:email></atom:email>
11
+ </atom:author>
12
+ <atom:link href=""/>
13
+ <description></description>
14
+ <TimeStamp>
15
+ <when></when>
16
+ </TimeStamp>
17
+ </Document>
18
+
19
+ <Folder>
20
+ <name></name>
21
+ <visibility>1</visibility>
22
+ <open>0</open>
23
+ <atom:author>
24
+ <atom:name></atom:name>!
25
+ <atom:uri></atom:uri>
26
+ <atom:email></atom:email>
27
+ </atom:author>
28
+ <atom:link href=""/>
29
+ <description></description>
30
+ <TimeStamp>
31
+ <when></when>
32
+ </TimeStamp>
33
+ </Folder>
34
+
35
+ <!-- Geometry -->
36
+ <Point id="ID">
37
+ <extrude>0</extrude>
38
+ <altitudeMode>clampToGround</altitudeMode> clampToGround, relativeToGround, absolute
39
+ <coordinates>lat,lon[,alt]</coordinates>
40
+ </Point>
41
+
42
+ <LineString id="ID">
43
+ <extrude>0</extrude>
44
+ <tassellate>0</tassellate>
45
+ <altitudeMode>clampToGround</altitudeMode>
46
+ <!-- or gx:altitudeMode: clampToSeaFloor, relativeToSeaFloor -->
47
+ <gx:drawOrder>0</gx:drawOrder>
48
+ <coordinates></coordinates>
49
+ </LineString>
50
+
51
+ <LinearRing>
52
+ <gx:altitudeOffset>0</gx:altitudeOffset>
53
+ <!-- same as LineString -->
54
+ </LinearRing>
55
+ </kml>
@@ -0,0 +1,9 @@
1
+ <trk>
2
+ <name></name>
3
+ <desc></desc>
4
+ <link href=""></link>
5
+ <number></number>
6
+ <trkseg>
7
+ <trkpt></trkpt>
8
+ </trkseg>
9
+ </trk>
@@ -0,0 +1,7 @@
1
+ <wpt lat="" lon="">
2
+ <ele></ele>
3
+ <time></time>
4
+ <name></name>
5
+ <desc></desc>
6
+ <link href=""/>
7
+ </wpt>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GPXKML
4
+ VERSION = '0.0.1'
5
+ end
data/lib/gpx_kml.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gpx_kml/version'
4
+ require 'gpx_kml/gpx'
5
+ require 'gpx_kml/kml'
6
+ require 'converter'
7
+
8
+ module GPXKML
9
+
10
+ include GPX
11
+ include KML
12
+ include CONVERTER
13
+
14
+ class GpxKml
15
+ def self.gpx_to_kml(file_path, destination_path)
16
+ CONVERTER::Converter.gpx_to_kml(file_path, destination_path)
17
+ end
18
+
19
+ def self.kml_to_gpx(file_path, destination_path)
20
+ CONVERTER::Converter.kml_to_gpx(file_path, destination_path)
21
+ end
22
+ end
23
+ end