Skip to content

Latest commit

 

History

History
157 lines (126 loc) · 4.11 KB

README.md

File metadata and controls

157 lines (126 loc) · 4.11 KB

Riley Water Consulting

Build Status Coverage Status Code Climate

Riley Water Consulting

Demo

Built With

  • Ruby on Rails - Used for parsing KML files, GeoJSON API endpoint, etc.
  • Bootstrap - CSS framework used for site design
  • Google Maps API - Used to draw points and polygons based on GeoJSON data from Rails

Relevant Code

# app/services/kml_parser.rb

class KmlParser
  def initialize(id, model_name)
    @id = id
    @model_name = model_name.constantize
  end

  def parse_polygon
    model = get_model
    doc = open_doc(model)
    coordinates_array = parse_coordinates(doc.at_css("polygon coordinates").text)
    polygon = 
      {
        type: "Polygon",
        coordinates: [
          coordinates_array
        ]
      }
    model.update_column(:polygon, polygon)
  end

  def parse_point
    model = get_model
    doc = open_doc(model) 
    coordinates_set = parse_coordinates(doc.at_css("point coordinates").text)
    point = 
      {
        type: "Point",
        coordinates: coordinates_set[0]
      }
    model.update_column(:point, point)
  end

private

  def get_model
    @model_name.find(@id)
  end
  
  def open_doc(model)
    Nokogiri::HTML(open(model.kml.url))
  end

  def parse_coordinates(coordinates)
    coordinates.scan(/(-?\d+.\d+),(-?\d+.\d+)/).collect { |lon, lat| [lon.to_f, lat.to_f]}
  end
end
# app/helpers/application_helper.rb

def static_map(geometry)
  # If polygon, encode polygon and attach to URL
  if geometry["type"] == "Polygon"
    encoded_poly = encode_polygon(geometry)
    image_tag URI.encode("https://maps.googleapis.com/maps/api/staticmap?key=#{google_maps_api_key}&size=200x200&path=fillcolor:0x00000077|color:0x000000FF|weight:2|enc:#{encoded_poly}")
  # If point, just attach point in lat,lon format
  elsif geometry["type"] == "Point"
    point = "#{geometry["coordinates"][1]},#{geometry["coordinates"][0]}"
    image_tag URI.encode("https://maps.googleapis.com/maps/api/staticmap?key=#{google_maps_api_key}&size=200x200&zoom=14&markers=#{point}")
  end
end

def encode_polygon(poly)
  coordinates = []
  # If more than 200 points in polygon, then simplify polygon
  if poly["coordinates"][0].length > 200
    simple_coordinates = simplify_coordinates(poly["coordinates"][0])
    # Parse coordinates into expected format for encode method
    simple_coordinates.each do |c|
      coordinates << [c[:y], c[:x]]
    end
  # If less than 200 points in polygon, just parse into expected format for encode method 
  else
    poly["coordinates"][0].each do |c|
      coordinates << [c[1], c[0]]
    end
  end
  # Encode points using Google encoded polyline algorithm
  Polylines::Encoder.encode_points(coordinates)
end

def simplify_coordinates(coordinates)
  # Parse coordinates into expected format for simplify method
  coordinates_hash = []
  coordinates.each do |c|
    coordinates_hash << {x: c[0], y: c[1]}
  end
  # Simplify coordinates using tolerance: 0.001
  SimplifyRb.simplify(coordinates_hash, 0.001)
end

Getting Started

Prerequisites

ruby -v     # 2.4.1
rails -v    # 5.1.3

Installing

Install dependencies

bundle install

Create .env file in project's root directory (to easily get a SECRET_KEY_BASE run rake secret)

RACK_ENV=development
SECRET_KEY_BASE=secret-key-base
S3_BUCKET_NAME=s3-bucket-name
AWS_ACCESS_KEY_ID=aws-id
AWS_SECRET_ACCESS_KEY=aws-secret-key
GOOGLE_MAPS_KEY=google-maps-key
SENDGRID_USERNAME=sendgrid-username
SENDGRID_PASSWORD=sendgrid-password

Setup database

rake db:setup

Run server

foreman start

Click a point or polygon on the map