simple-trail 0.0.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/simple_trail/manipulation/enricher.rb +98 -0
- data/lib/simple_trail/manipulation/straightener.rb +6 -5
- data/lib/simple_trail/parser/gpx.rb +7 -1
- data/lib/simple_trail.rb +1 -0
- data/simple-trail.gemspec +1 -1
- data/spec/examples/gss20-full-official.gpx +44524 -0
- data/spec/examples/pois.gpx +2 -0
- data/spec/examples/zyleta2021.gpx +3894 -0
- data/spec/manipulation/enricher_spec.rb +38 -0
- data/spec/parser/gpx_poi_spec.rb +9 -0
- metadata +12 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a356f88eab11c5803bf0896ed044d6c19a1968e3150a3695d25cc2768ac61ec5
|
4
|
+
data.tar.gz: 4ccb055143d1a205229bead38b230c72e98e0dcd4eb76f0be3bcd3322317db6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9289dafe44a05855959d5f3c05902bba234f9ade2978ddb524fe563620bfcb6dbf897e6b582818395d16b56ad362bd31770f27a27efe445171224355ef6785f9
|
7
|
+
data.tar.gz: b9c3af1d741cc970ffefa67facc556bc5a5cb65293b968167bd2cd0a6dcf0953bc3895b6284d0fadffcd775e4c7de6eb2c2c1423f918cabbc074584914c65183
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Manipulation
|
4
|
+
class Enricher
|
5
|
+
attr_reader :enriched_points
|
6
|
+
|
7
|
+
def initialize(points, distance_limit=nil)
|
8
|
+
@points = points
|
9
|
+
@distance_limit = distance_limit
|
10
|
+
@counter = 3
|
11
|
+
end
|
12
|
+
|
13
|
+
def enrich
|
14
|
+
add_points_where_big_gaps
|
15
|
+
recalculate_distances
|
16
|
+
add_total_distance
|
17
|
+
add_km_markers
|
18
|
+
|
19
|
+
@enriched_points = @points
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def add_points_where_big_gaps
|
25
|
+
detect_gaps
|
26
|
+
@gaps.any? ? points_with_gaps_field : @points
|
27
|
+
end
|
28
|
+
|
29
|
+
def points_with_gaps_field
|
30
|
+
return @points if @gaps.none? || @counter.zero?
|
31
|
+
|
32
|
+
offset = 0
|
33
|
+
@gaps.each do |gap|
|
34
|
+
middle_point = calculate_middle_point(@points[gap[:origin] + offset], @points[gap[:destination] + offset])
|
35
|
+
@points = @points.insert(gap[:destination] + offset, {lat: middle_point.lat, lon: middle_point.lng })
|
36
|
+
|
37
|
+
offset += 1
|
38
|
+
end
|
39
|
+
@counter -= 1
|
40
|
+
add_points_where_big_gaps
|
41
|
+
end
|
42
|
+
|
43
|
+
def calculate_middle_point(loc1, loc2)
|
44
|
+
latlan(loc1).midpoint_to(latlan(loc2))
|
45
|
+
end
|
46
|
+
|
47
|
+
def detect_gaps
|
48
|
+
gap_limit = @distance_limit || 0.1
|
49
|
+
@gaps = []
|
50
|
+
@points.each_cons(2).with_index do |pair, i|
|
51
|
+
distance = calculate_distance(pair[0], pair[1])
|
52
|
+
@gaps << {origin: i, destination: i+1, distance: distance} if distance > gap_limit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def recalculate_distances
|
57
|
+
@points.each_cons(2).with_index do |pair, i|
|
58
|
+
distance = calculate_distance(pair[0], pair[1])
|
59
|
+
@points[i+1].merge!(distance: distance)
|
60
|
+
end
|
61
|
+
@points[0].merge!(distance: 0.0)
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_total_distance
|
65
|
+
@points.each_with_index do |point, i|
|
66
|
+
new_total = if i.zero?
|
67
|
+
point[:distance]
|
68
|
+
else !point[:distance].nil? && !@points[i-1][:total_distance].nil?
|
69
|
+
point[:distance] + @points[i-1][:total_distance]
|
70
|
+
end
|
71
|
+
@points[i].merge!(total_distance: new_total)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_km_markers
|
76
|
+
total_distance = @points[-1][:total_distance].floor - 1
|
77
|
+
total_distance.times do |i|
|
78
|
+
find_and_enrich_first_occurence(i+1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_and_enrich_first_occurence(i)
|
83
|
+
index = @points.find_index{|point| point[:total_distance] > i}
|
84
|
+
@points[index].merge!(label: i)
|
85
|
+
end
|
86
|
+
|
87
|
+
def calculate_distance(loc1, loc2)
|
88
|
+
return 0.0 if loc2.nil?
|
89
|
+
latlan(loc1).distance_to(latlan(loc2))
|
90
|
+
rescue
|
91
|
+
end
|
92
|
+
|
93
|
+
def latlan(location)
|
94
|
+
Geokit::LatLng.new(location[:lat] || location['lat'], location[:lon] || location['lon'])
|
95
|
+
rescue
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module Manipulation
|
4
4
|
class Straightener
|
5
|
+
attr_reader :points, :cluster_groups
|
6
|
+
|
5
7
|
def initialize(points)
|
6
8
|
@points = points
|
7
9
|
@latlng_points = @points.map { |p| Geokit::LatLng.new(p[:lat], p[:lon]) }
|
@@ -10,12 +12,11 @@ module Manipulation
|
|
10
12
|
def points_without_clusters
|
11
13
|
@average_distance_between ||= average_distance_between
|
12
14
|
@possible_clusters = detect_clusters
|
13
|
-
|
15
|
+
straighten_points!
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
group_clusters
|
18
|
-
straighten_points!
|
18
|
+
def cluster_groups
|
19
|
+
@cluster_groups ||= group_clusters
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
@@ -42,7 +43,7 @@ module Manipulation
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def straighten_points!
|
45
|
-
|
46
|
+
cluster_groups.each do |cluster_group|
|
46
47
|
cluster_coords = @points.values_at(*cluster_group)
|
47
48
|
avg_lat = cluster_coords.map { |cc| cc[:lat].to_f }.inject(:+) / cluster_coords.size
|
48
49
|
avg_lon = cluster_coords.map { |cc| cc[:lon].to_f }.inject(:+) / cluster_coords.size
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Parser
|
4
4
|
class Gpx
|
5
|
-
attr_reader :simplified_points, :points, :parsed_file
|
5
|
+
attr_reader :simplified_points, :points, :points_of_interests, :parsed_file
|
6
6
|
|
7
7
|
def initialize(filename)
|
8
8
|
@filename = filename
|
@@ -11,7 +11,9 @@ module Parser
|
|
11
11
|
def read
|
12
12
|
file = File.new(@filename)
|
13
13
|
@parsed_file = XmlHasher.parse(file)[:gpx]
|
14
|
+
fail unless @parsed_file
|
14
15
|
extract_points
|
16
|
+
extract_pois
|
15
17
|
end
|
16
18
|
|
17
19
|
def meta
|
@@ -26,6 +28,10 @@ module Parser
|
|
26
28
|
@simplified_points = @points.map { |point| point.select { |key, _| [:lon, :lat].include? key } }
|
27
29
|
end
|
28
30
|
|
31
|
+
def extract_pois
|
32
|
+
@points_of_interests = @parsed_file[:wpt]
|
33
|
+
end
|
34
|
+
|
29
35
|
def extract_data
|
30
36
|
metadata = @parsed_file[:metadata]
|
31
37
|
{
|
data/lib/simple_trail.rb
CHANGED
@@ -7,6 +7,7 @@ require File.expand_path('simple_trail/parser/gpx', __dir__)
|
|
7
7
|
require File.expand_path('simple_trail/manipulation/statistics', __dir__)
|
8
8
|
require File.expand_path('simple_trail/manipulation/straightener', __dir__)
|
9
9
|
require File.expand_path('simple_trail/manipulation/unifier', __dir__)
|
10
|
+
require File.expand_path('simple_trail/manipulation/enricher', __dir__)
|
10
11
|
|
11
12
|
module SimpleTrail
|
12
13
|
Geokit.default_units = :kms
|
data/simple-trail.gemspec
CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'simple-trail'
|
8
|
-
s.version = '0.
|
8
|
+
s.version = '0.1.2'
|
9
9
|
s.date = '2020-08-03'
|
10
10
|
s.summary = 'Readind and manipulating GPX and other trail representation file'
|
11
11
|
s.description = 'Optimazing and manipulating GPX file data. For my private purposes mostly'
|