gpx_doctor 0.4.0 → 0.5.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 +4 -4
- data/README.md +31 -1
- data/lib/gpx_doctor/parser.rb +48 -1
- data/lib/gpx_doctor/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 804ebe2457e24c9688e6e8993d0dc3d4adab7b7fddc27478706eaf72a9d09f59
|
|
4
|
+
data.tar.gz: e1bb3e8d17ff968a1cd6414c736d9f444559f447d5e6cc8dd3c79175a394b68b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f8e5bd2ab41937b0faa004c5d1c1ae3c422ba9d332e3aa1ea353fe7f9c22706c0f53e5b3c8161361e8d38ead9bed4fa516d7415d580cc912bdc3976452107dfb
|
|
7
|
+
data.tar.gz: 68e78f3a4f84027272a1a96127b998d2a00c447e1f0b75daff611a8d3123c374df0ab6ebf92563e6ab516a4ff9d2bcaa2540dabdad8358a9d35f87fd4cd23860
|
data/README.md
CHANGED
|
@@ -89,7 +89,8 @@ result = GpxDoctor::Parser.parse("path/to/file.gpx", params: {
|
|
|
89
89
|
max_points: 500, # reduce each segment to at most this many points
|
|
90
90
|
segment_statistics: true, # compute distance_to_next, elevation_change, direction for each point
|
|
91
91
|
cumulative_distance: true, # add cumulative distance from start of each segment/route
|
|
92
|
-
enhance_elevation: true
|
|
92
|
+
enhance_elevation: true, # fetch missing elevations from the configured elevation server
|
|
93
|
+
full_poi_data: true # populate result.pois with start/finish boundary data for the whole GPX and each track segment
|
|
93
94
|
})
|
|
94
95
|
```
|
|
95
96
|
|
|
@@ -100,11 +101,14 @@ Processing is applied in the following order:
|
|
|
100
101
|
3. `segment_statistics` — per-point statistics (distance, bearing, elevation change)
|
|
101
102
|
4. `cumulative_distance` — cumulative distance from the start of each segment/route
|
|
102
103
|
5. `enhance_elevation` — elevation lookup via the elevation server
|
|
104
|
+
6. `full_poi_data` — POI boundary extraction (start, finish, and per-segment boundaries)
|
|
103
105
|
|
|
104
106
|
`enhance_elevation: true` requires the elevation server to be configured (see **Configuration** above). It only fills in points that have no elevation value; existing elevations are left unchanged.
|
|
105
107
|
|
|
106
108
|
`cumulative_distance: true` adds a `cumulative_distance` field to each point, representing the cumulative distance in kilometers from the start of its segment or route. For tracks with multiple segments, each segment's cumulative distance starts at 0.0 (gaps between segments are not included in the calculation).
|
|
107
109
|
|
|
110
|
+
`full_poi_data: true` populates `result.pois` with the first and last geographic point of the entire GPX (across all routes and track segments), plus optional per-segment boundary data. Distances within each segment start at 0.0 and reflect that segment's length only. The `ele` key is omitted for points that have no elevation value. The global `finish` distance is the sum of all individual collection lengths. See **`result.pois`** below for the output shape.
|
|
111
|
+
|
|
108
112
|
## Accessing data
|
|
109
113
|
|
|
110
114
|
```ruby
|
|
@@ -113,6 +117,7 @@ result.waypoints # => [#<Waypoint …>] (top-level <wpt> elements only)
|
|
|
113
117
|
result.routes # => [#<Route …>]
|
|
114
118
|
result.tracks # => [#<Track …>]
|
|
115
119
|
result.metadata # => #<Metadata …> (or nil)
|
|
120
|
+
result.pois # => Hash (only when parsed with full_poi_data: true, otherwise nil)
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
`result.points` is a flat array containing **all** geographic points from:
|
|
@@ -120,6 +125,31 @@ result.metadata # => #<Metadata …> (or nil)
|
|
|
120
125
|
- `<rtept>` elements inside each `<rte>`
|
|
121
126
|
- `<trkpt>` elements inside each `<trkseg>` inside each `<trk>`
|
|
122
127
|
|
|
128
|
+
### `result.pois`
|
|
129
|
+
|
|
130
|
+
When parsed with `full_poi_data: true`, `result.pois` contains boundary data for the entire GPX and each track segment:
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
result = GpxDoctor::Parser.parse("route.gpx", params: { full_poi_data: true })
|
|
134
|
+
result.pois
|
|
135
|
+
# =>
|
|
136
|
+
# {
|
|
137
|
+
# start: { lon: 16.38, lat: 48.23, ele: 170.0, distance: 0.0 },
|
|
138
|
+
# finish: { lon: 16.39, lat: 48.24, ele: 175.0, distance: 1.42 },
|
|
139
|
+
# segments: [
|
|
140
|
+
# {
|
|
141
|
+
# start: { lon: 16.38, lat: 48.23, ele: 170.0, distance: 0.0 },
|
|
142
|
+
# finish: { lon: 16.39, lat: 48.24, ele: 175.0, distance: 1.42 }
|
|
143
|
+
# }
|
|
144
|
+
# ]
|
|
145
|
+
# }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- **`start`** / **`finish`** — first and last geographic point across all routes and track segments, each with `lon`, `lat`, `distance` (and `ele` when present). `start` always has `distance: 0.0`; `finish` distance is the sum of all individual route/segment lengths.
|
|
149
|
+
- **`segments`** — present only when the GPX contains track segments. Each entry is `{start:, finish:}` for one `<trkseg>`, with distances measured from the beginning of that segment (`start` is always `distance: 0.0`).
|
|
150
|
+
- The `ele` key is omitted for points that have no elevation value.
|
|
151
|
+
- Distance values respect the configured `unit_system` (kilometres for `:metric`, miles for `:imperial`).
|
|
152
|
+
|
|
123
153
|
## Building GPX files
|
|
124
154
|
|
|
125
155
|
The `GpxDoctor::Builder` class generates GPX 1.1 XML from a `Result` object (the same structure returned by the parser).
|
data/lib/gpx_doctor/parser.rb
CHANGED
|
@@ -7,7 +7,7 @@ module GpxDoctor
|
|
|
7
7
|
class Parser
|
|
8
8
|
GPX_NS = 'http://www.topografix.com/GPX/1/1'
|
|
9
9
|
|
|
10
|
-
Result = Struct.new(:waypoints, :routes, :tracks, :metadata, keyword_init: true) do
|
|
10
|
+
Result = Struct.new(:waypoints, :routes, :tracks, :metadata, :pois, keyword_init: true) do
|
|
11
11
|
def points
|
|
12
12
|
waypoints + routes.flat_map(&:points) + tracks.flat_map(&:points)
|
|
13
13
|
end
|
|
@@ -55,6 +55,7 @@ module GpxDoctor
|
|
|
55
55
|
enhance_statistics(result) if @params[:segment_statistics]
|
|
56
56
|
enhance_cumulative_distance(result) if @params[:cumulative_distance]
|
|
57
57
|
enhance_elevations(result) if @params[:enhance_elevation]
|
|
58
|
+
result.pois = build_pois(result) if @params[:full_poi_data]
|
|
58
59
|
|
|
59
60
|
result
|
|
60
61
|
end
|
|
@@ -276,5 +277,51 @@ module GpxDoctor
|
|
|
276
277
|
track.segments.each { |seg| enhancer.enhance(seg.points) }
|
|
277
278
|
end
|
|
278
279
|
end
|
|
280
|
+
|
|
281
|
+
def point_to_poi(point, distance)
|
|
282
|
+
poi = { lon: point.lon, lat: point.lat }
|
|
283
|
+
poi[:ele] = point.ele if point.ele
|
|
284
|
+
poi[:distance] = distance
|
|
285
|
+
poi
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def build_pois(result)
|
|
289
|
+
collections = result.routes.map(&:points) +
|
|
290
|
+
result.tracks.flat_map { |t| t.segments.map(&:points) }
|
|
291
|
+
non_empty = collections.reject(&:empty?)
|
|
292
|
+
|
|
293
|
+
return {} if non_empty.empty?
|
|
294
|
+
|
|
295
|
+
total_distance = non_empty.sum { |pts| collection_distance(pts) }
|
|
296
|
+
|
|
297
|
+
pois = {
|
|
298
|
+
start: point_to_poi(non_empty.first.first, 0.0),
|
|
299
|
+
finish: point_to_poi(non_empty.last.last, total_distance)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
segments_pois = result.tracks.flat_map do |track|
|
|
303
|
+
track.segments.filter_map do |seg|
|
|
304
|
+
next if seg.points.empty?
|
|
305
|
+
|
|
306
|
+
{
|
|
307
|
+
start: point_to_poi(seg.points.first, 0.0),
|
|
308
|
+
finish: point_to_poi(seg.points.last, collection_distance(seg.points))
|
|
309
|
+
}
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
pois[:segments] = segments_pois unless segments_pois.empty?
|
|
314
|
+
pois
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def collection_distance(points)
|
|
318
|
+
return 0.0 if points.length < 2
|
|
319
|
+
|
|
320
|
+
unit_system = GpxDoctor.configuration.unit_system
|
|
321
|
+
points.each_cons(2).sum do |a, b|
|
|
322
|
+
dist_km = DistanceCalculator.distance(a, b) / 1000.0
|
|
323
|
+
UnitConverter.convert_cumulative_distance(dist_km, unit_system)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
279
326
|
end
|
|
280
327
|
end
|
data/lib/gpx_doctor/version.rb
CHANGED