Class: GpxDoctor::PointLabeler
- Inherits:
-
Object
- Object
- GpxDoctor::PointLabeler
- Defined in:
- lib/gpx_doctor/point_labeler.rb
Constant Summary collapse
- EPSILON =
Tolerance (in the configured distance unit) used to decide whether a label distance coincides with an existing point, to avoid inserting a near-duplicate point right next to it.
1e-9
Instance Method Summary collapse
-
#label(points, label_interval) ⇒ Object
Inserts an interpolated point at every multiple of
label_intervalmeasured as cumulative distance from the start ofpoints(kilometres for :metric, miles for :imperial — see GpxDoctor.configuration.unit_system).
Instance Method Details
#label(points, label_interval) ⇒ Object
Inserts an interpolated point at every multiple of label_interval
measured as cumulative distance from the start of points (kilometres
for :metric, miles for :imperial — see GpxDoctor.configuration.unit_system).
When points already carry a cumulative_distance (set by
GpxDoctor::CumulativeDistanceEnhancer), those values are reused instead
of being recalculated. Otherwise cumulative distance is computed from
scratch.
Existing points are left untouched. A new point is inserted between the
two existing points that bracket each label distance, with lat/lon
always interpolated, and ele/time interpolated only when both endpoints
have values. The new point's label field is set to the target
distance (e.g. 1.0 for the point at the 1.0 km/mi mark).
A label distance that falls (within a small tolerance) on an existing point is skipped — no duplicate point is inserted.
Returns a new array; the original is not mutated. When points has
fewer than 2 elements, or label_interval is nil, zero or negative,
the original array is returned unchanged.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/gpx_doctor/point_labeler.rb', line 31 def label(points, label_interval) return points if points.nil? || points.size < 2 || label_interval.nil? || label_interval <= 0 cumulative = cumulative_distances(points) result = [points.first] label_interval = label_interval.to_f target = label_interval points.each_cons(2).with_index do |(a, b), i| start_dist = cumulative[i] end_dist = cumulative[i + 1] while target <= end_dist + EPSILON if target > start_dist + EPSILON && target < end_dist - EPSILON result << interpolate(a, b, start_dist, end_dist, target) end target += label_interval end result << b end result end |