Class: GpxDoctor::PointSelector
- Inherits:
-
Object
- Object
- GpxDoctor::PointSelector
- Defined in:
- lib/gpx_doctor/point_selector.rb
Instance Method Summary collapse
-
#select(points, max_points) ⇒ Object
Selects up to
max_pointspoints frompointswith equal distance spread. -
#total_distance(points) ⇒ Object
Returns the total distance in meters for a sequence of
points.
Instance Method Details
#select(points, max_points) ⇒ Object
Selects up to max_points points from points with equal distance spread. Always includes the first and last points. Returns a new array; the original is not mutated. When points already has fewer or equal elements than max_points, it is returned unchanged.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/gpx_doctor/point_selector.rb', line 18 def select(points, max_points) return points if points.nil? || max_points <= 0 || points.size <= max_points m = points.size n = max_points # For n == 1 there is no denominator (n - 1 = 0), so just keep the first point. return [points[0]] if n == 1 cumulative = [0.0] points.each_cons(2) do |a, b| cumulative << cumulative.last + DistanceCalculator.distance(a, b) end total = cumulative.last # Degenerate case: all points are at the same location — fall back to index spread. if total.zero? indices = (0...n).map { |i| (i * (m - 1).to_f / (n - 1)).round } return indices.uniq.map { |idx| points[idx] } end used = {} selected_indices = (0...n).map do |i| target = i * total / (n - 1).to_f # Find the closest unused point to the target cumulative distance. best_idx = cumulative .each_with_index .reject { |_, idx| used[idx] } .min_by { |d, _| (d - target).abs } .last used[best_idx] = true best_idx end selected_indices.sort.map { |idx| points[idx] } end |
#total_distance(points) ⇒ Object
Returns the total distance in meters for a sequence of points.
6 7 8 9 10 11 12 |
# File 'lib/gpx_doctor/point_selector.rb', line 6 def total_distance(points) return 0.0 if points.nil? || points.size < 2 total = 0.0 points.each_cons(2) { |a, b| total += DistanceCalculator.distance(a, b) } total end |