class Manipulation::Straightener

Constants

BASIC_CLUSTER_CHECK_RATIO
BASIC_CLUSTER_CHECK_SIZE
BASIC_SAMPLE_SIZE

Attributes

cluster_groups[R]
points[R]

Public Class Methods

new(points) click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 7
def initialize(points)
  @points = points
  @latlng_points = @points.map { |p| Geokit::LatLng.new(p[:lat], p[:lon]) }
end

Public Instance Methods

points_without_clusters() click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 12
def points_without_clusters
  @average_distance_between ||= average_distance_between
  @possible_clusters = detect_clusters
  straighten_points!
end

Private Instance Methods

average_distance_between() click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 56
def average_distance_between
  sample_points = (0..@points.size - 2).to_a.sample(BASIC_SAMPLE_SIZE)
  sample_points.map do |i|
    start = @latlng_points[i]
    finish = @latlng_points[i + 1]
    start.distance_to(finish)
  end.inject(:+) / sample_points.size
end
detect_clusters() click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 65
def detect_clusters
  (0..@points.size - BASIC_CLUSTER_CHECK_SIZE - 1).to_a.map do |i|
    start = @latlng_points[i]
    finish = @latlng_points[i + BASIC_CLUSTER_CHECK_SIZE]
    distance = start.distance_to(finish)
    i if distance < @average_distance_between * BASIC_CLUSTER_CHECK_SIZE * BASIC_CLUSTER_CHECK_RATIO
  end
end
group_clusters() click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 28
def group_clusters
  @cluster_groups = []
  @possible_clusters.each do |index|
    @group ||= []
    if index.nil?
      unless @group.empty?
        @cluster_groups << @group
        @group = []
      end
      next
    else
      @group << index
    end
  end
  @cluster_groups << @group unless @group.empty?
end
straighten_points!() click to toggle source
# File lib/simple_trail/manipulation/straightener.rb, line 45
def straighten_points!
  cluster_groups.each do |cluster_group|
    cluster_coords = @points.values_at(*cluster_group)
    avg_lat = cluster_coords.map { |cc| cc[:lat].to_f }.inject(:+) / cluster_coords.size
    avg_lon = cluster_coords.map { |cc| cc[:lon].to_f }.inject(:+) / cluster_coords.size
    @points[cluster_group.first][:lat] = avg_lat.to_s
    @points[cluster_group.first][:lon] = avg_lon.to_s
    cluster_group.drop(1).each { |index| @points.delete_at(index) }
  end
end