lots of rails gpx stuff

This commit is contained in:
Steve Coast 2006-12-01 20:38:29 +00:00
parent 92418b7954
commit 93dab8a127
7 changed files with 227 additions and 14 deletions

View file

@ -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

View file

@ -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'

View file

@ -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 %>

View 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 %>

View file

@ -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

View file

@ -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

View file

@ -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