lots of rails gpx stuff
This commit is contained in:
parent
92418b7954
commit
93dab8a127
7 changed files with 227 additions and 14 deletions
|
@ -10,6 +10,11 @@ class TraceController < ApplicationController
|
|||
@traces = Trace.find(:all, :conditions => ['user_id = ?', @user.id])
|
||||
end
|
||||
|
||||
def view
|
||||
@trace = Trace.find(params[:id])
|
||||
render :nothing, :status => 401 if @trace.user.id != @user.id
|
||||
end
|
||||
|
||||
def create
|
||||
filename = "/tmp/#{rand}"
|
||||
|
||||
|
@ -28,4 +33,15 @@ class TraceController < ApplicationController
|
|||
|
||||
redirect_to :action => 'mine'
|
||||
end
|
||||
|
||||
def picture
|
||||
trace = Trace.find(params[:id])
|
||||
send_data(trace.large_picture, :filename => "#{trace.id}.gif", :type => 'image/png', :disposition => 'inline') if trace.public
|
||||
end
|
||||
|
||||
def icon
|
||||
trace = Trace.find(params[:id])
|
||||
send_data(trace.icon_picture, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline') if trace.public
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
class Tracepoint < ActiveRecord::Base
|
||||
set_table_name 'gps_points'
|
||||
|
||||
validates_numericality_of :latitude
|
||||
validates_numericality_of :longitude
|
||||
# validates_numericality_of :latitude
|
||||
# validates_numericality_of :longitude
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :trace, :foreign_key => 'gpx_id'
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<tr>
|
||||
<% cl = cycle('table0', 'table1') %>
|
||||
<td class="<%= cl %>">image here</td>
|
||||
<td class="<%= cl %>">
|
||||
<% if trace.inserted %>
|
||||
<a href="<%= url_for :controller => 'trace', :action => 'view', :id => trace.id, :user_login => trace.user.display_name %>">
|
||||
<img src="<%= url_for :controller => 'trace', :action => 'icon', :id => trace.id, :user_login => trace.user.display_name %>" border="0">
|
||||
</a>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="<%= cl %>"><%= link_to trace.name, {:controller => 'trace', :action => 'onetrace', :id => trace.id} %>
|
||||
<span class="gpxsummary" title="<%= trace.timestamp %>"> ...
|
||||
<% if trace.inserted %>
|
||||
|
|
15
app/views/trace/view.rhtml
Normal file
15
app/views/trace/view.rhtml
Normal file
|
@ -0,0 +1,15 @@
|
|||
trace <%= @trace.name %>
|
||||
<br>
|
||||
icon <img src="<%= url_for :controller => 'trace', :action => 'icon', :id => @trace.id, :user_login => @trace.user.display_name %>" border="0">
|
||||
<br>
|
||||
|
||||
picture <img src="<%= url_for :controller => 'trace', :action => 'picture', :id => @trace.id, :user_login => @trace.user.display_name %>" border="0">
|
||||
|
||||
<br>
|
||||
time <%= @trace.timestamp %>
|
||||
<br>
|
||||
dec <%= @trace.description %>
|
||||
|
||||
|
||||
|
||||
|
|
@ -28,10 +28,14 @@ ActionController::Routing::Routes.draw do |map|
|
|||
map.connect '/logout.html', :controller => 'user', :action => 'logout'
|
||||
map.connect '/create-account.html', :controller => 'user', :action => 'new'
|
||||
map.connect '/forgot-password.html', :controller => 'user', :action => 'lost_password'
|
||||
|
||||
|
||||
# traces
|
||||
map.connect '/traces', :controller => 'trace', :action => 'list'
|
||||
map.connect '/traces/mine', :controller => 'trace', :action => 'mine'
|
||||
map.connect '/traces/user/:user/:id', :controller => 'trace', :action => 'list', :id => nil
|
||||
map.connect '/traces/user/:user_login/:id', :controller => 'trace', :action => 'view', :id => nil
|
||||
map.connect '/traces/user/:user_login/:id/picture', :controller => 'trace', :action => 'picture', :id => nil
|
||||
map.connect '/traces/user/:user_login/:id/icon', :controller => 'trace', :action => 'icon', :id => nil
|
||||
|
||||
# fall through
|
||||
map.connect ':controller/:action/:id'
|
||||
end
|
||||
|
|
|
@ -36,19 +36,34 @@ while($running) do
|
|||
gpx.points do |point|
|
||||
tp = Tracepoint.new
|
||||
tp.latitude = point['latitude']
|
||||
tp.latitude = point['longitude']
|
||||
tp.longitude = point['longitude']
|
||||
tp.altitude = point['altitude']
|
||||
tp.user_id = trace.user.id
|
||||
tp.gpx_id = trace.id
|
||||
tp.trackid = point['segment']
|
||||
end
|
||||
trace.size = gpx.actual_points
|
||||
trace.inserted = true
|
||||
trace.save
|
||||
Notifier::deliver_gpx_success(trace, gpx.possible_points)
|
||||
tp.save!
|
||||
end
|
||||
|
||||
if gpx.actual_points > 0
|
||||
max_lat = Tracepoint.maximum('latitude', :conditions => ['gpx_id = ?', trace.id])
|
||||
min_lat = Tracepoint.minimum('latitude', :conditions => ['gpx_id = ?', trace.id])
|
||||
max_lon = Tracepoint.maximum('longitude', :conditions => ['gpx_id = ?', trace.id])
|
||||
min_lon = Tracepoint.minimum('longitude', :conditions => ['gpx_id = ?', trace.id])
|
||||
#logger.info("bbox: #{min_lat} #{max_lat} #{min_lon} #{max_lon}")
|
||||
trace.large_picture = gpx.get_picture(min_lat, min_lon, max_lat, max_lon, gpx.actual_points)
|
||||
trace.icon_picture = gpx.get_icon(min_lat, min_lon, max_lat, max_lon)
|
||||
trace.size = gpx.actual_points
|
||||
trace.inserted = true
|
||||
trace.save
|
||||
Notifier::deliver_gpx_success(trace, gpx.possible_points)
|
||||
else
|
||||
#trace.destroy
|
||||
Notifier::deliver_gpx_failure(trace, '0 points parsed ok. Do they all have lat,lng,alt,timestamp?')
|
||||
end
|
||||
|
||||
rescue Exception => ex
|
||||
trace.destroy
|
||||
Notifier::deliver_gpx_failure(trace, ex.to_s)
|
||||
#trace.destroy
|
||||
Notifier::deliver_gpx_failure(trace, ex.to_s + ex.backtrace.join("\n") )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
159
lib/osm.rb
159
lib/osm.rb
|
@ -7,10 +7,58 @@ module OSM
|
|||
#
|
||||
# gpx = OSM:GPXImporter.new('somefile.gpx')
|
||||
# gpx.points {|p| puts p['latitude']}
|
||||
|
||||
|
||||
require 'time'
|
||||
require 'rexml/parsers/sax2parser'
|
||||
require 'rexml/text'
|
||||
require 'RMagick'
|
||||
|
||||
class Mercator
|
||||
include Math
|
||||
|
||||
def initialize(lat, lon, degrees_per_pixel, width, height)
|
||||
#init me with your centre lat/lon, the number of degrees per pixel and the size of your image
|
||||
@clat = lat
|
||||
@clon = lon
|
||||
@degrees_per_pixel = degrees_per_pixel
|
||||
@width = width
|
||||
@height = height
|
||||
@dlon = width / 2 * degrees_per_pixel
|
||||
@dlat = height / 2 * degrees_per_pixel * cos(@clat * PI / 180)
|
||||
|
||||
@tx = xsheet(@clon - @dlon)
|
||||
@ty = ysheet(@clat - @dlat)
|
||||
|
||||
@bx = xsheet(@clon + @dlon)
|
||||
@by = ysheet(@clat + @dlat)
|
||||
|
||||
end
|
||||
|
||||
#the following two functions will give you the x/y on the entire sheet
|
||||
|
||||
def kilometerinpixels
|
||||
return 40008.0 / 360.0 * @degrees_per_pixel
|
||||
end
|
||||
|
||||
def ysheet(lat)
|
||||
log(tan(PI / 4 + (lat * PI / 180 / 2)))
|
||||
end
|
||||
|
||||
def xsheet(lon)
|
||||
lon
|
||||
end
|
||||
|
||||
#and these two will give you the right points on your image. all the constants can be reduced to speed things up. FIXME
|
||||
|
||||
def y(lat)
|
||||
return @height - ((ysheet(lat) - @ty) / (@by - @ty) * @height)
|
||||
end
|
||||
|
||||
def x(lon)
|
||||
return ((xsheet(lon) - @tx) / (@bx - @tx) * @width)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class GPXImporter
|
||||
attr_reader :possible_points
|
||||
|
@ -73,5 +121,114 @@ module OSM
|
|||
end
|
||||
parser.parse
|
||||
end
|
||||
|
||||
def get_picture(min_lat, min_lon, max_lat, max_lon, num_points)
|
||||
frames = 10
|
||||
width = 250
|
||||
height = 250
|
||||
rat= Math.cos( ((max_lat + min_lat)/2.0) / 180.0 * 3.141592)
|
||||
proj = OSM::Mercator.new((min_lat + max_lat) / 2, (max_lon + min_lon) / 2, (max_lat - min_lat) / width / rat, width, height)
|
||||
|
||||
images = []
|
||||
|
||||
frames.times do
|
||||
gc = Magick::Draw.new
|
||||
gc.stroke_linejoin('miter')
|
||||
gc.stroke('#FFFFFF')
|
||||
gc.fill('#FFFFFF')
|
||||
gc.rectangle(0,0,width,height)
|
||||
gc.stroke_width(1)
|
||||
images << gc
|
||||
end
|
||||
|
||||
oldpx = 0.0
|
||||
oldpy = 0.0
|
||||
|
||||
first = true
|
||||
|
||||
m = 0
|
||||
mm = 0
|
||||
points do |p|
|
||||
px = proj.x(p['longitude'])
|
||||
py = proj.y(p['latitude'])
|
||||
frames.times do |n|
|
||||
images[n].stroke_width(1)
|
||||
images[n].stroke('#BBBBBB')
|
||||
images[n].fill('#BBBBBB')
|
||||
images[n].line(px, py, oldpx, oldpy ) unless first
|
||||
end
|
||||
images[mm].stroke_width(3)
|
||||
images[mm].stroke('#000000')
|
||||
images[mm].fill('#000000')
|
||||
images[mm].line(px, py, oldpx, oldpy ) unless first
|
||||
|
||||
m +=1
|
||||
if m > num_points.to_f / frames.to_f * (mm+1)
|
||||
mm += 1
|
||||
end
|
||||
first = false
|
||||
oldpy = py
|
||||
oldpx = px
|
||||
end
|
||||
|
||||
il = Magick::ImageList.new
|
||||
|
||||
frames.times do |n|
|
||||
canvas = Magick::Image.new(width, height) {
|
||||
self.background_color = 'white'
|
||||
}
|
||||
begin
|
||||
images[n].draw(canvas)
|
||||
rescue ArgumentError
|
||||
end
|
||||
canvas.format = 'GIF'
|
||||
il << canvas
|
||||
end
|
||||
|
||||
il.delay = 50
|
||||
il.format = 'GIF'
|
||||
return il.to_blob
|
||||
end
|
||||
|
||||
def get_icon(min_lat, min_lon, max_lat, max_lon)
|
||||
width = 50
|
||||
height = 50
|
||||
rat= Math.cos( ((max_lat + min_lat)/2.0) / 180.0 * 3.141592)
|
||||
proj = OSM::Mercator.new((min_lat + max_lat) / 2, (max_lon + min_lon) / 2, (max_lat - min_lat) / width / rat, width, height)
|
||||
|
||||
images = []
|
||||
|
||||
gc = Magick::Draw.new
|
||||
gc.stroke_linejoin('miter')
|
||||
|
||||
oldpx = 0.0
|
||||
oldpy = 0.0
|
||||
|
||||
first = true
|
||||
|
||||
gc.stroke_width(1)
|
||||
gc.stroke('#000000')
|
||||
gc.fill('#000000')
|
||||
|
||||
points do |p|
|
||||
px = proj.x(p['longitude'])
|
||||
py = proj.y(p['latitude'])
|
||||
gc.line(px, py, oldpx, oldpy ) unless first
|
||||
first = false
|
||||
oldpy = py
|
||||
oldpx = px
|
||||
end
|
||||
|
||||
canvas = Magick::Image.new(width, height) {
|
||||
self.background_color = 'white'
|
||||
}
|
||||
begin
|
||||
gc.draw(canvas)
|
||||
rescue ArgumentError
|
||||
end
|
||||
canvas.format = 'GIF'
|
||||
return canvas.to_blob
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue