Class: GpxDoctor::PointLabeler

Inherits:
Object
  • Object
show all
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

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