simple-trail 0.0.3 → 0.1.3
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 +99 -0
- data/lib/simple_trail/parser/gpx.rb +6 -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 +39 -0
- data/spec/parser/gpx_poi_spec.rb +9 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 459bc2473757a35abbd5659ecf848e89dfc31e09e6febd66bb730fa3c872fc6e
|
4
|
+
data.tar.gz: 2e28ca43a36e63de9fdf2ea295b1c4d3166544b4ec581f3daf9ae81ad74247bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba4d5bd4951e88a62175e7c5c13520e0c3eaee7a662db893007a7568dd6e2c29a53a310a6f7e19c157afa00f993e6f491b11d397a49428114e5f8bda20eaf778
|
7
|
+
data.tar.gz: d4684d613afba62b5c2a0ca890566bdbb33d029b64f7e207e96157aa6985222ae78c5940c4d21e3d2d12327c20a5858dab192b4fd5d05ccdffbf97f4c276265e
|
@@ -0,0 +1,99 @@
|
|
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
|
+
est_elevation = (@points[gap[:origin] + offset][:ele].to_f + @points[gap[:destination] + offset][:ele].to_f) / 2.0
|
36
|
+
@points = @points.insert(gap[:destination] + offset, {lat: middle_point.lat, lon: middle_point.lng, ele: est_elevation })
|
37
|
+
|
38
|
+
offset += 1
|
39
|
+
end
|
40
|
+
@counter -= 1
|
41
|
+
add_points_where_big_gaps
|
42
|
+
end
|
43
|
+
|
44
|
+
def calculate_middle_point(loc1, loc2)
|
45
|
+
latlan(loc1).midpoint_to(latlan(loc2))
|
46
|
+
end
|
47
|
+
|
48
|
+
def detect_gaps
|
49
|
+
gap_limit = @distance_limit || 0.1
|
50
|
+
@gaps = []
|
51
|
+
@points.each_cons(2).with_index do |pair, i|
|
52
|
+
distance = calculate_distance(pair[0], pair[1])
|
53
|
+
@gaps << {origin: i, destination: i+1, distance: distance} if distance > gap_limit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def recalculate_distances
|
58
|
+
@points.each_cons(2).with_index do |pair, i|
|
59
|
+
distance = calculate_distance(pair[0], pair[1])
|
60
|
+
@points[i+1].merge!(distance: distance)
|
61
|
+
end
|
62
|
+
@points[0].merge!(distance: 0.0)
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_total_distance
|
66
|
+
@points.each_with_index do |point, i|
|
67
|
+
new_total = if i.zero?
|
68
|
+
point[:distance]
|
69
|
+
else !point[:distance].nil? && !@points[i-1][:total_distance].nil?
|
70
|
+
point[:distance] + @points[i-1][:total_distance]
|
71
|
+
end
|
72
|
+
@points[i].merge!(total_distance: new_total)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_km_markers
|
77
|
+
total_distance = @points[-1][:total_distance].floor - 1
|
78
|
+
total_distance.times do |i|
|
79
|
+
find_and_enrich_first_occurence(i+1)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_and_enrich_first_occurence(i)
|
84
|
+
index = @points.find_index{|point| point[:total_distance] > i}
|
85
|
+
@points[index].merge!(label: i)
|
86
|
+
end
|
87
|
+
|
88
|
+
def calculate_distance(loc1, loc2)
|
89
|
+
return 0.0 if loc2.nil?
|
90
|
+
latlan(loc1).distance_to(latlan(loc2))
|
91
|
+
rescue
|
92
|
+
end
|
93
|
+
|
94
|
+
def latlan(location)
|
95
|
+
Geokit::LatLng.new(location[:lat] || location['lat'], location[:lon] || location['lon'])
|
96
|
+
rescue
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -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
|
@@ -13,6 +13,7 @@ module Parser
|
|
13
13
|
@parsed_file = XmlHasher.parse(file)[:gpx]
|
14
14
|
fail unless @parsed_file
|
15
15
|
extract_points
|
16
|
+
extract_pois
|
16
17
|
end
|
17
18
|
|
18
19
|
def meta
|
@@ -27,6 +28,10 @@ module Parser
|
|
27
28
|
@simplified_points = @points.map { |point| point.select { |key, _| [:lon, :lat].include? key } }
|
28
29
|
end
|
29
30
|
|
31
|
+
def extract_pois
|
32
|
+
@points_of_interests = @parsed_file[:wpt]
|
33
|
+
end
|
34
|
+
|
30
35
|
def extract_data
|
31
36
|
metadata = @parsed_file[:metadata]
|
32
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.3'
|
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'
|