class GPS2Map::GPS2Map

Class that takes an input file containing GPS co-ordinates and outputs an HTML file containing a Google Map of those co-ordinates.

Public Instance Methods

generate(input_file, output_file) click to toggle source
# File lib/gps2map.rb, line 27
def generate(input_file, output_file)
  vars           = {}
  vars[:api_key] = ENV['GOOGLE_MAPS_API_KEY'] || abort('No GOOGLE_MAPS_API_KEY provided.')
  vars[:title]   = input_file
  coordinates    = []
  markers        = []
  label          = 0
  latitudes, longitudes = parse_file(input_file)
  interval = latitudes.length / options[:markers]

  latitudes.each_with_index do |latitude, i|
    longitude = longitudes[i]
    coordinates << Coordinate.new(latitude, longitude)
    markers << Marker.new(latitude, longitude, label += 1) if i > 1 && (i % interval).zero?
  end

  vars[:coordinates]     = coordinates
  vars[:markers]         = markers
  vars[:map_centre_lat]  = mean_of(coordinates.map(&:latitude)) + LATITUDE_OFFSET
  vars[:map_centre_long] = mean_of(coordinates.map(&:longitude))
  vars[:map_start_lat]   = coordinates.first.latitude
  vars[:map_start_long]  = coordinates.first.longitude
  write_output_file(output_file, execute_template(vars))
  puts "Plotted #{latitudes.length.to_comma_formatted} co-ordinates with #{markers.length} markers."
end

Private Instance Methods

execute_template(variables) click to toggle source
# File lib/gps2map.rb, line 55
def execute_template(variables)
  template = File.join(__dir__, 'map.erb')
  context = OpenStruct.new(variables).instance_eval { binding }
  # Set the ERB trim mode to suppress newlines.
  ERB.new(File.read(template), 0, '>').result(context)
end
mean_of(coordinates) click to toggle source
# File lib/gps2map.rb, line 62
def mean_of(coordinates)
  coordinates.sum.fdiv(coordinates.length).round(DIGITS)
end
parse(input_file, selector) { |el| ... } click to toggle source
# File lib/gps2map.rb, line 77
def parse(input_file, selector)
  File.open(input_file, 'r') do |fi|
    doc = Nokogiri::XML(fi)
    doc.css(selector).each { |el| yield(el) }
  end
rescue Errno::EACCES
  abort("Permission denied when attemping to read input file '#{input_file}'")
rescue Errno::ENOENT
  abort("Input file '#{input_file}' doesn't exist.")
end
parse_file(input_file) click to toggle source
# File lib/gps2map.rb, line 66
def parse_file(input_file)
  case File.extname(input_file).downcase
  when '.gpx'
    parse_gpx(input_file)
  when '.kml'
    parse_kml(input_file)
  when '.tcx'
    parse_tcx(input_file)
  end
end
parse_gpx(input_file) click to toggle source
# File lib/gps2map.rb, line 88
def parse_gpx(input_file)
  latitudes  = []
  longitudes = []
  parse(input_file, 'trkpt') do |el|
    latitudes  << el['lat'].to_f.round(DIGITS)
    longitudes << el['lon'].to_f.round(DIGITS)
  end
  [latitudes, longitudes]
end
parse_kml(input_file) click to toggle source
# File lib/gps2map.rb, line 98
def parse_kml(input_file)
  latitudes  = []
  longitudes = []
  parse(input_file, 'Point coordinates') do |el|
    # KML has longitude first.
    longitudes << CSV.parse(el.text.strip).first.first.to_f.round(DIGITS)
    latitudes  << CSV.parse(el.text.strip).first[1].to_f.round(DIGITS)
  end
  [latitudes, longitudes]
end
parse_tcx(input_file) click to toggle source
# File lib/gps2map.rb, line 109
def parse_tcx(input_file)
  latitudes  = []
  longitudes = []
  File.open(input_file, 'r') do |fi|
    doc = Nokogiri::XML(fi)
    doc.css('LatitudeDegrees').each { |el| latitudes << el.text.to_f.round(DIGITS) }
    doc.css('LongitudeDegrees').each { |el| longitudes << el.text.to_f.round(DIGITS) }
  end
  [latitudes, longitudes]
end
write_output_file(output_file, data) click to toggle source
# File lib/gps2map.rb, line 120
def write_output_file(output_file, data)
  File.open(output_file, 'w') { |fi| fi.write(data) }
rescue Errno::EACCES
  abort("Permission denied when attemping to write output file '#{output_file}'")
rescue Errno::ENOENT
  abort("Output file path '#{output_file}' doesn't exist.")
end