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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0ba71f5752f36af3efd9f3b12de47d843a85b3ecd7fbcabd7468a2eef43355e
4
- data.tar.gz: b58cb9eb1f207c3ec26f127b615ba43f70efe741904c6e73aa2c4ab059a7b710
3
+ metadata.gz: 804ebe2457e24c9688e6e8993d0dc3d4adab7b7fddc27478706eaf72a9d09f59
4
+ data.tar.gz: e1bb3e8d17ff968a1cd6414c736d9f444559f447d5e6cc8dd3c79175a394b68b
5
5
  SHA512:
6
- metadata.gz: 053df672b67de8623f4749e7a5d0e8419667abd7227e31a8937d2434ebad3a0af73d04ae54af95112ecffe1e7824314634316cc1bc1793863d5c9289057cf4bd
7
- data.tar.gz: 2376c74be6339f8aeeb535e8f79dbd9dd876bca7526713f9be8e09da3793718eaba4e285a455e4a07e1f182768affcf206c6ae7ba81483e37c6468e59bf96e27
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 # fetch missing elevations from the configured elevation server
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).
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GpxDoctor
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gpx_doctor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Poltrax