mirror of
https://github.com/publiclab/mapknitter.git
synced 2025-12-05 16:00:00 +01:00
* Try migrating from Travis to GitHub Actions for CI * Update actions.yml and tests.yml * Add ruby version * Update config/database.yml.example * Try rubocop and docker jobs * Fix indentation * Update tests.yml * Update tests.yml * Update gemfile * Update rubocop job and Gemfile * Update .rubocop_shopify_styleguide.yml * Update gemfile * Update .rubocop_todo.yml * Update rubocop configuration and styleguides * Fix rubocop offenses * Update .rubocop.yml * Update .rubocop.yml * Udate .codeclimate.yml * Update .codeclimate.yml * Update .codeclimate.yml * Update .codeclimate.yml * Setup unit tests * Update find_verified_user method in connection.rb * Add yarn cache and install to setup * install exporter dependencies; gdal/imagemagick * Introduce Gitpod to migration work (#1538) * Add CORS headers (#1536) * Create .gitpod.dockerfile * Create .gitpod.yml * Create database.yml.gitpod * Update .gitpod.yml * ruby 2.4.6 in gitpod.dockerfile * Update .gitpod.yml * Update database.yml.gitpod Co-authored-by: Sebastian Silva <sebastian@fuentelibre.org> Co-authored-by: Jeffrey Warren <jeff@unterbahn.com> * Install gdal and use egordm for yarn cache * Delete unnecessary query and fix layout * Run script with verbose output * Try installing package in action.yml * Setup controllers job * Fix indentation * Setup system tests job * Setup docker development build job * Fix identifiers * Fix path to action.yml * Update development dockerfile * Setup docker production build job * Update tests.yml * Setup assets precompilation job * Setup production environment * Update tests.yml * Update action.yml for production * Try with test setup * Remove action.yml for production * Change names of jobs for friendliness and clarity * Update .github/workflows/tests.yml Co-authored-by: Jeffrey Warren <jeff@unterbahn.com> * Move dockerfiles to directory and change docker job names for clarity * Update docker job names Co-authored-by: Jeffrey Warren <jeff@unterbahn.com> Co-authored-by: Sebastian Silva <sebastian@fuentelibre.org>
171 lines
4.9 KiB
Ruby
Executable File
171 lines
4.9 KiB
Ruby
Executable File
class Warpable < ApplicationRecord
|
|
attr_accessor :image
|
|
attr_accessor :src, :srcmedium # for json generation
|
|
|
|
require 'cartagen'
|
|
|
|
# Paperclip; config and production/development specific configs
|
|
# in /config/initializers/paperclip.rb
|
|
has_attached_file :image,
|
|
s3_protocol: 'https',
|
|
styles: {
|
|
medium: "500x375",
|
|
small: "240x180",
|
|
thumb: "100x100>",
|
|
}
|
|
|
|
validates_attachment_content_type :image, content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"]
|
|
|
|
belongs_to :map, optional: true
|
|
belongs_to :user, optional: true
|
|
|
|
has_paper_trail on: %i(create update), only: %i(nodes)
|
|
|
|
# overriding JSON formatting for Leaflet.DistortableImage
|
|
def as_json(options = {})
|
|
json = super(options)
|
|
json[:src] = image.url
|
|
json[:srcmedium] = image.url(:medium)
|
|
json[:nodes] = nodes_array
|
|
json
|
|
end
|
|
|
|
# JSON formatting for file upload plugin
|
|
def fup_json
|
|
{ "name" => read_attribute(:image_filename),
|
|
"size" => read_attribute(:image_size),
|
|
"url" => image.url(:medium),
|
|
"original_url" => image.url(:original),
|
|
"id" => read_attribute(:id),
|
|
"thumbnail_url" => image.url(:thumb),
|
|
"delete_url" => image.url,
|
|
"delete_type" => "DELETE" }
|
|
end
|
|
|
|
def fup_error_json
|
|
{ "name" => read_attribute(:image_filename),
|
|
"size" => read_attribute(:image_size),
|
|
"error" => errors["base"] }
|
|
end
|
|
|
|
after_save :save_dimensions
|
|
|
|
# this runs each time warpable is moved/distorted,
|
|
# to calculate resolution
|
|
def save_dimensions
|
|
path = image.options[:storage] == :s3 ? image.url : image.path
|
|
geo = Paperclip::Geometry.from_file(path.sub('https', 'http'))
|
|
|
|
update_column(:width, geo.width)
|
|
update_column(:height, geo.height)
|
|
end
|
|
|
|
# if has non-nil width and has nodes, it's been placed.
|
|
def placed?
|
|
!width.nil? && nodes != ''
|
|
end
|
|
|
|
def poly_area
|
|
area = 0
|
|
nodes = nodes_array
|
|
nodes.each_with_index do |node, index|
|
|
nextnode = if index < nodes.length - 1
|
|
nodes[index + 1]
|
|
else
|
|
nodes[0]
|
|
end
|
|
last = if index.positive?
|
|
nodes[index - 1]
|
|
else
|
|
nodes[nodes.length - 1]
|
|
end
|
|
scale = 20_037_508.34
|
|
# inefficient but workable, we don't use this that often:
|
|
|
|
nodey = Cartagen.spherical_mercator_lat_to_y(node.lat, scale)
|
|
nodex = Cartagen.spherical_mercator_lon_to_x(node.lon, scale)
|
|
lasty = Cartagen.spherical_mercator_lat_to_y(last.lat, scale)
|
|
lastx = Cartagen.spherical_mercator_lon_to_x(last.lon, scale)
|
|
nexty = Cartagen.spherical_mercator_lat_to_y(nextnode.lat, scale)
|
|
nextx = Cartagen.spherical_mercator_lon_to_x(nextnode.lon, scale)
|
|
area += lastx * nodey - nodex * lasty + nodex * nexty - nextx * nodey
|
|
end
|
|
(area / 2).abs
|
|
end
|
|
|
|
# crude measure based on image width, as resolution can vary
|
|
# across image if it's not flat on the earth
|
|
def get_cm_per_pixel
|
|
unless width.nil? || nodes == ''
|
|
nodes = nodes_array
|
|
# haversine might be more appropriate for large images
|
|
scale = 20_037_508.34
|
|
y1 = Cartagen.spherical_mercator_lat_to_y(nodes[0].lat, scale)
|
|
x1 = Cartagen.spherical_mercator_lon_to_x(nodes[0].lon, scale)
|
|
y2 = Cartagen.spherical_mercator_lat_to_y(nodes[1].lat, scale)
|
|
x2 = Cartagen.spherical_mercator_lon_to_x(nodes[1].lon, scale)
|
|
dist = Math.sqrt(((y2 - y1) * (y2 - y1)) + ((x2 - x1) * (x2 - x1)))
|
|
scale = (dist * 100) / width unless width.nil? || dist.nil?
|
|
end
|
|
scale
|
|
end
|
|
|
|
def self.histogram_cm_per_pixel
|
|
w = Warpable.where('cm_per_pixel != 0 AND cm_per_pixel < 500')
|
|
.order('cm_per_pixel DESC')
|
|
if !w.empty?
|
|
hist = []
|
|
(0..w.first.cm_per_pixel.to_i).each do |bin|
|
|
hist[bin] = 0
|
|
end
|
|
w.each do |warpable|
|
|
hist[warpable.cm_per_pixel.to_i] += 1
|
|
end
|
|
hist
|
|
else
|
|
[]
|
|
end
|
|
end
|
|
|
|
def nodes_array
|
|
Node.find(nodes.split(','))
|
|
end
|
|
|
|
# allow uploads via URL
|
|
# needs update for Paperclip!!
|
|
require 'open-uri'
|
|
attr_reader :url
|
|
def url=(uri)
|
|
nil if uri.blank?
|
|
|
|
io = (begin
|
|
URI.parse(uri).open
|
|
rescue StandardError
|
|
nil
|
|
end)
|
|
(class << io; self; end;).class_eval do
|
|
define_method(:original_filename) { base_uri.path.split('/').last }
|
|
end
|
|
self.uploaded_data = io
|
|
end
|
|
|
|
# TODO: simplify/reduce # of parameters needed here:
|
|
def generate_perspectival_distort(pxperm, path)
|
|
Exporter.generate_perspectival_distort(pxperm, path, nodes_array, id, image_file_name, image, height, width)
|
|
end
|
|
|
|
def user_id
|
|
Map.find(map_id)
|
|
map.user_id
|
|
end
|
|
|
|
# adjust filename behavior of Paperclip after migrating from attachment_fu
|
|
Paperclip.interpolates(:custom_filename) do |attachment, style|
|
|
if style == :original
|
|
basename(attachment, style) # generate hash path here
|
|
else
|
|
"#{basename(attachment, style)}_#{style}" # generate hash path here
|
|
end
|
|
end
|
|
end
|