From: Gabriel Ebner Date: Thu, 20 Sep 2007 14:37:29 +0000 (+0000) Subject: Merge rails_port as of r4613 & fix tests. X-Git-Tag: live~8129^2~18 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/cfbdd3f7e1c688e2c875ded9fd847fcc1c3a4caf?hp=6d44c78407ea9a553be030f3f7c49b48d616878b Merge rails_port as of r4613 & fix tests. --- diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index d30043e59..99c2a48cd 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -43,6 +43,8 @@ class AmfController < ApplicationController when 'putway'; results[index]=putdata(index,putway(args)) when 'deleteway'; results[index]=putdata(index,deleteway(args)) when 'makeway'; results[index]=putdata(index,makeway(args)) + when 'putpoi'; results[index]=putdata(index,putpoi(args)) + when 'getpoi'; results[index]=putdata(index,getpoi(args)) end end @@ -71,8 +73,8 @@ class AmfController < ApplicationController def getpresets presets={} - presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[] - presetnames={}; presetnames['point']={}; presetnames['way']={} + presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[] + presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={} presettype='' presetcategory='' @@ -97,8 +99,8 @@ unclassified road: highway=unclassified,name=(type road name) way/footway footpath: highway=footway,foot=yes -bridleway: highway=bridleway,foot=yes,horse=yes,bicycle=yes -byway: highway=byway,foot=yes,horse=yes,bicycle=yes,motorcar=yes +bridleway: highway=bridleway,foot=yes +byway: highway=unsurfaced,foot=yes permissive path: highway=footway,foot=permissive way/cycleway @@ -124,13 +126,8 @@ disused railway tracks: railway=disused course of old railway: railway=abandoned way/natural -forest: natural=wood,landuse=forest -woodland: natural=wood,landuse= -reservoir: natural=water,landuse=reservoir -lake: natural=water,landuse= -marsh: natural=marsh -beach: natural=beach -coastline: natural=coastline +lake: landuse=water +forest: landuse=forest point/road mini roundabout: highway=mini_roundabout @@ -158,7 +155,33 @@ viaduct: railway=viaduct level crossing: railway=crossing point/natural -peak: natural=peak +peak: point=peak + +POI/road +car park: amenity=parking +petrol station: amenity=fuel + +POI/cycleway +bike park: amenity=bicycle_parking + +POI/place +city: place=city,name=(type name here),is_in=(type region or county) +town: place=town,name=(type name here),is_in=(type region or county) +suburb: place=suburb,name=(type name here),is_in=(type region or county) +village: place=village,name=(type name here),is_in=(type region or county) +hamlet: place=hamlet,name=(type name here),is_in=(type region or county) + +POI/tourism +attraction: tourism=attraction,amenity=,religion=,denomination= +church: tourism=,amenity=place_of_worship,name=(type name here),religion=christian,denomination=(type denomination here) +hotel: tourism=hotel,amenity=,religion=,denomination= +other religious: tourism=,amenity=place_of_worship,name=(type name here),religion=(type religion),denomination= +post box: amenity=post_box,tourism=,name=,religion=,denomination= +post office: amenity=post_office,tourism=,name=,religion=,denomination= +pub: tourism=,amenity=pub,name=(type name here),religion=,denomination= + +POI/natural +peak: point=peak EOF StringIO.open(txt) do |file| @@ -192,6 +215,9 @@ EOF ymin = args[1].to_f-0.01 xmax = args[2].to_f+0.01 ymax = args[3].to_f+0.01 + baselong = args[4] + basey = args[5] + masterscale = args[6] RAILS_DEFAULT_LOGGER.info(" Message: whichways, bbox=#{xmin},#{ymin},#{xmax},#{ymax}") @@ -207,7 +233,7 @@ EOF ways = waylist.collect {|a| a.wayid.to_i } # get an array of way id's - pointlist =ActiveRecord::Base.connection.select_all("SELECT current_nodes.id,current_nodes.tags "+ + pointlist =ActiveRecord::Base.connection.select_all("SELECT current_nodes.id,latitude,longitude,current_nodes.tags "+ " FROM current_nodes "+ " LEFT OUTER JOIN current_segments cs1 ON cs1.node_a=current_nodes.id "+ " LEFT OUTER JOIN current_segments cs2 ON cs2.node_b=current_nodes.id "+ @@ -216,7 +242,7 @@ EOF " AND cs1.id IS NULL AND cs2.id IS NULL "+ " AND current_nodes.visible=1") - points = pointlist.collect {|a| [a['id'],tag2array(a['tags'])] } # get a list of node ids and their tags + points = pointlist.collect {|a| [a['id'],long2coord(a['longitude'].to_f,baselong,masterscale),lat2coord(a['latitude'].to_f,basey,masterscale),tag2array(a['tags'])] } # get a list of node ids and their tags return [ways,points] end @@ -443,6 +469,49 @@ EOF [originalway,way,renumberednodes,numberedsegments,xmin,xmax,ymin,ymax] end + # ----- putpoi (user token, id, x,y,tag array,visible,baselong,basey,masterscale) + # returns current id, new id + # if new: add new row to current_nodes and nodes + # if old: add new row to nodes, update current_nodes + + def putpoi(args) + usertoken,id,x,y,tags,visible,baselong,basey,masterscale=args + uid=getuserid(usertoken) + return if !uid + db_now='@now'+uid.to_s+id.to_i.abs.to_s+Time.new.to_i.to_s # 'now' variable name, typically 51 chars + ActiveRecord::Base.connection.execute("SET #{db_now}=NOW()") + + id=id.to_i + visible=visible.to_i + x=coord2long(x.to_f,masterscale,baselong) + y=coord2lat(y.to_f,masterscale,basey) + tagsql="'"+sqlescape(array2tag(tags))+"'" + + if (id>0) then + ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{id},#{y},#{x},#{db_now},#{uid},#{visible},#{tagsql})"); + ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{y},longitude=#{x},timestamp=#{db_now},user_id=#{uid},visible=#{visible},tags=#{tagsql} WHERE id=#{id}"); + newid=id + else + newid=ActiveRecord::Base.connection.insert("INSERT INTO current_nodes (latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{y},#{x},#{db_now},#{uid},#{visible},#{tagsql})"); + ActiveRecord::Base.connection.update("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags) VALUES (#{newid},#{y},#{x},#{db_now},#{uid},#{visible},#{tagsql})"); + end + [id,newid] + end + + # ----- getpoi (id,baselong,basey,masterscale) + # returns id,x,y,tag array + + def getpoi(args) + id,baselong,basey,masterscale=args; id=id.to_i + poi=ActiveRecord::Base.connection.select_one("SELECT latitude,longitude,tags "+ + "FROM current_nodes WHERE visible=1 AND id=#{id}") + if poi.nil? then return [nil,nil,nil,''] end + [id, + long2coord(poi['longitude'].to_f,baselong,masterscale), + lat2coord(poi['latitude'].to_f,basey,masterscale), + tag2array(poi['tags'])] + end + # ----- deleteway (user token, way) # returns way ID only @@ -691,18 +760,33 @@ end def createuniquenodes(uqs_name,uqn_name) # Finds nodes which appear in uniquesegments but no other segments sql=<<-EOF - CREATE TEMPORARY TABLE #{uqn_name} - SELECT DISTINCT node_id - FROM (SELECT cn.id AS node_id - FROM current_nodes AS cn, - current_segments AS cs, - #{uqs_name} AS us - WHERE cs.id=us.segment_id - AND (cn.id=cs.node_a OR cn.id=cs.node_b)) AS n - LEFT JOIN current_segments AS cs2 ON node_id=cs2.node_a AND cs2.visible=1 - LEFT JOIN current_segments AS cs3 ON node_id=cs3.node_b AND cs3.visible=1 - WHERE cs2.node_a IS NULL - AND cs3.node_b IS NULL + CREATE TEMPORARY TABLE #{uqn_name} + SELECT DISTINCT node_id + FROM (SELECT cn.id AS node_id + FROM current_nodes AS cn, + current_segments AS cs, + #{uqs_name} AS us + WHERE cs.id=us.segment_id + AND cn.id=cs.node_a) AS n + LEFT JOIN current_segments AS cs2 ON node_id=cs2.node_a AND cs2.visible=1 + LEFT JOIN current_segments AS cs3 ON node_id=cs3.node_b AND cs3.visible=1 + WHERE cs2.node_a IS NULL + AND cs3.node_b IS NULL + EOF + ActiveRecord::Base.connection.execute(sql) + sql=<<-EOF + INSERT INTO #{uqn_name} + SELECT DISTINCT node_id + FROM (SELECT cn.id AS node_id + FROM current_nodes AS cn, + current_segments AS cs, + #{uqs_name} AS us + WHERE cs.id=us.segment_id + AND cn.id=cs.node_b) AS n + LEFT JOIN current_segments AS cs2 ON node_id=cs2.node_a AND cs2.visible=1 + LEFT JOIN current_segments AS cs3 ON node_id=cs3.node_b AND cs3.visible=1 + WHERE cs2.node_a IS NULL + AND cs3.node_b IS NULL EOF ActiveRecord::Base.connection.execute(sql) end diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 44ae65285..6e8e77c2f 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -63,13 +63,8 @@ class ApiController < ApplicationController return end - # integerise - min_lat = min_lat * 1000000 - max_lat = max_lat * 1000000 - min_lon = min_lon * 1000000 - max_lon = max_lon * 1000000 # get all the points - points = Tracepoint.find(:all, :conditions => ['latitude BETWEEN ? AND ? AND longitude BETWEEN ? AND ?', min_lat.to_i, max_lat.to_i, min_lon.to_i, max_lon.to_i], :select => "DISTINCT *", :offset => offset, :limit => TRACEPOINTS_PER_PAGE, :order => "timestamp DESC" ) + points = Tracepoint.find_by_area(min_lat, min_lon, max_lat, max_lon, :offset => offset, :limit => TRACEPOINTS_PER_PAGE, :order => "timestamp DESC" ) doc = XML::Document.new doc.encoding = 'UTF-8' @@ -142,8 +137,7 @@ class ApiController < ApplicationController end # get all the nodes - nodes = Node.find(:all, :conditions => - ['latitude > ? AND longitude > ? AND latitude < ? AND longitude < ? AND visible = 1', min_lat, min_lon, max_lat, max_lon]) + nodes = Node.find(:all, :conditions => ['latitude BETWEEN ? AND ? AND longitude BETWEEN ? AND ? AND visible = 1', min_lat, max_lat, min_lon, max_lon]) node_ids = nodes.collect {|node| node.id } diff --git a/app/controllers/diary_entry_controller.rb b/app/controllers/diary_entry_controller.rb index 92f541332..e763dfd72 100644 --- a/app/controllers/diary_entry_controller.rb +++ b/app/controllers/diary_entry_controller.rb @@ -7,9 +7,9 @@ class DiaryEntryController < ApplicationController def new @title = 'new diary entry' if params[:diary_entry] - @entry = DiaryEntry.new(params[:diary_entry]) - @entry.user = @user - if @entry.save + @diary_entry = DiaryEntry.new(params[:diary_entry]) + @diary_entry.user = @user + if @diary_entry.save redirect_to :controller => 'diary_entry', :action => 'list', :display_name => @user.display_name end end @@ -41,10 +41,7 @@ class DiaryEntryController < ApplicationController end @entries.each do |entry| - # add geodata here - latitude = nil - longitude = nil - rss.add(latitude, longitude, entry.title, entry.user.display_name, url_for({:controller => 'diary_entry', :action => 'list', :id => entry.id, :display_name => entry.user.display_name}), entry.body, entry.created_at) + rss.add(entry.latitude, entry.longitude, entry.title, entry.user.display_name, url_for({:controller => 'diary_entry', :action => 'list', :id => entry.id, :display_name => entry.user.display_name}), entry.body, entry.created_at) end render :text => rss.to_s, :content_type => "application/rss+xml" diff --git a/app/controllers/message_controller.rb b/app/controllers/message_controller.rb index f52274cd0..52f38e9f6 100644 --- a/app/controllers/message_controller.rb +++ b/app/controllers/message_controller.rb @@ -7,23 +7,16 @@ class MessageController < ApplicationController def new @title = 'send message' if params[:message] - to_user = User.find(params[:user_id]) - body = params[:message][:body] - title = params[:message][:title] - message = Message.new - message.body = body - message.title = title - message.to_user_id = params[:user_id] - message.from_user_id = @user.id - message.sent_on = Time.now + @message = Message.new(params[:message]) + @message.to_user_id = params[:user_id] + @message.from_user_id = @user.id + @message.sent_on = Time.now - if message.save + if @message.save flash[:notice] = 'Message sent' + Notifier::deliver_message_notification(@message) redirect_to :controller => 'message', :action => 'inbox', :display_name => @user.display_name - else - @message.errors.add("Sending message failed") end - end end diff --git a/app/controllers/node_controller.rb b/app/controllers/node_controller.rb index de81f188b..7c7e3e6e4 100644 --- a/app/controllers/node_controller.rb +++ b/app/controllers/node_controller.rb @@ -13,12 +13,9 @@ class NodeController < ApplicationController if node node.user_id = @user.id node.visible = true + node.save_with_history! - if node.save_with_history - render :text => node.id.to_s, :content_type => "text/plain" - else - render :nothing => true, :status => :internal_server_error - end + render :text => node.id.to_s, :content_type => "text/plain" else render :nothing => true, :status => :bad_request end @@ -38,8 +35,6 @@ class NodeController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end @@ -55,12 +50,9 @@ class NodeController < ApplicationController node.latitude = new_node.latitude node.longitude = new_node.longitude node.tags = new_node.tags + node.save_with_history! - if node.save_with_history - render :nothing => true - else - render :nothing => true, :status => :internal_server_error - end + render :nothing => true else render :nothing => true, :status => :bad_request end @@ -69,8 +61,6 @@ class NodeController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end @@ -86,7 +76,8 @@ class NodeController < ApplicationController else node.user_id = @user.id node.visible = 0 - node.save_with_history + node.save_with_history! + render :nothing => true end else @@ -94,8 +85,6 @@ class NodeController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end diff --git a/app/controllers/relation_controller.rb b/app/controllers/relation_controller.rb index efd5bf9dc..d00e9e077 100644 --- a/app/controllers/relation_controller.rb +++ b/app/controllers/relation_controller.rb @@ -15,12 +15,9 @@ class RelationController < ApplicationController render :nothing => true, :status => :precondition_failed else relation.user_id = @user.id + relation.save_with_history! - if relation.save_with_history - render :text => relation.id.to_s, :content_type => "text/plain" - else - render :text => "save error", :status => :internal_server_error - end + render :text => relation.id.to_s, :content_type => "text/plain" end else render :nothing => true, :status => :bad_request @@ -61,12 +58,9 @@ class RelationController < ApplicationController relation.tags = new_relation.tags relation.members = new_relation.members relation.visible = true + relation.save_with_history! - if relation.save_with_history - render :nothing => true - else - render :nothing => true, :status => :internal_server_error - end + render :nothing => true end else render :nothing => true, :status => :bad_request @@ -94,12 +88,9 @@ class RelationController < ApplicationController relation.tags = [] relation.members = [] relation.visible = false + relation.save_with_history! - if relation.save_with_history - render :nothing => true - else - render :nothing => true, :status => :internal_server_error - end + render :nothing => true end else render :nothing => true, :status => :gone diff --git a/app/controllers/swf_controller.rb b/app/controllers/swf_controller.rb index 33e2ee4a6..6b29d1535 100644 --- a/app/controllers/swf_controller.rb +++ b/app/controllers/swf_controller.rb @@ -20,10 +20,10 @@ class SwfController < ApplicationController basey =params['basey'].to_f masterscale =params['masterscale'].to_f - xmin=params['xmin'].to_f; xminr=xmin/0.000001 - xmax=params['xmax'].to_f; xmaxr=xmax/0.000001 - ymin=params['ymin'].to_f; yminr=ymin/0.000001 - ymax=params['ymax'].to_f; ymaxr=ymax/0.000001 + xmin=params['xmin'].to_f; + xmax=params['xmax'].to_f; + ymin=params['ymin'].to_f; + ymax=params['ymax'].to_f; # - Begin movie @@ -47,20 +47,18 @@ class SwfController < ApplicationController if params['token'] user=User.authenticate(:token => params[:token]) - sql="SELECT gps_points.latitude*0.000001 AS lat,gps_points.longitude*0.000001 AS lon,gpx_files.id AS fileid,UNIX_TIMESTAMP(gps_points.timestamp) AS ts "+ + sql="SELECT gps_points.latitude*0.0000001 AS lat,gps_points.longitude*0.0000001 AS lon,gpx_files.id AS fileid,UNIX_TIMESTAMP(gps_points.timestamp) AS ts "+ " FROM gpx_files,gps_points "+ "WHERE gpx_files.id=gpx_id "+ " AND gpx_files.user_id=#{user.id} "+ - " AND (gps_points.longitude BETWEEN #{xminr} AND #{xmaxr}) "+ - " AND (gps_points.latitude BETWEEN #{yminr} AND #{ymaxr}) "+ + " AND "+OSM.sql_for_area(ymin,xmin,ymax,xmax,"gps_points.")+ " AND (gps_points.timestamp IS NOT NULL) "+ "ORDER BY fileid DESC,ts "+ "LIMIT 10000" else - sql="SELECT latitude*0.000001 AS lat,longitude*0.000001 AS lon,gpx_id AS fileid,UNIX_TIMESTAMP(timestamp) AS ts "+ + sql="SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,gpx_id AS fileid,UNIX_TIMESTAMP(timestamp) AS ts "+ " FROM gps_points "+ - "WHERE (longitude BETWEEN #{xminr} AND #{xmaxr}) "+ - " AND (latitude BETWEEN #{yminr} AND #{ymaxr}) "+ + "WHERE "+OSM.sql_for_area(ymin,xmin,ymax,xmax,"gps_points.")+ " AND (gps_points.timestamp IS NOT NULL) "+ "ORDER BY fileid DESC,ts "+ "LIMIT 10000" diff --git a/app/controllers/way_controller.rb b/app/controllers/way_controller.rb index 2ef960c6e..2e0623df4 100644 --- a/app/controllers/way_controller.rb +++ b/app/controllers/way_controller.rb @@ -15,12 +15,9 @@ class WayController < ApplicationController render :nothing => true, :status => :precondition_failed else way.user_id = @user.id + way.save_with_history! - if way.save_with_history - render :text => way.id.to_s, :content_type => "text/plain" - else - render :nothing => true, :status => :internal_server_error - end + render :text => way.id.to_s, :content_type => "text/plain" end else render :nothing => true, :status => :bad_request @@ -41,8 +38,6 @@ class WayController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end @@ -61,12 +56,9 @@ class WayController < ApplicationController way.tags = new_way.tags way.nds = new_way.nds way.visible = true + way.save_with_history! - if way.save_with_history - render :nothing => true - else - render :nothing => true, :status => :internal_server_error - end + render :nothing => true end else render :nothing => true, :status => :bad_request @@ -76,8 +68,6 @@ class WayController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end @@ -93,20 +83,17 @@ class WayController < ApplicationController way.tags = [] way.nds = [] way.visible = false + way.save_with_history! - if way.save_with_history - render :nothing => true - else - render :nothing => true, :status => :internal_server_error - end + render :nothing => true end else render :nothing => true, :status => :gone end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error + rescue => ex + puts ex end end @@ -131,8 +118,6 @@ class WayController < ApplicationController end rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found - rescue - render :nothing => true, :status => :internal_server_error end end diff --git a/app/helpers/geocoder_helper.rb b/app/helpers/geocoder_helper.rb index c337b5ed6..f1b4e01dd 100644 --- a/app/helpers/geocoder_helper.rb +++ b/app/helpers/geocoder_helper.rb @@ -2,7 +2,7 @@ module GeocoderHelper def result_to_html(result) html_options = {} #html_options[:title] = strip_tags(result[:description]) if result[:description] - html_options[:href] = "?lat=#{result[:lat]}&lon=#{result[:lon]}&zoom=#{result[:zoom]}" + html_options[:href] = "?mlat=#{result[:lat]}&mlon=#{result[:lon]}&zoom=#{result[:zoom]}" html = "" html << result[:prefix] if result[:prefix] html << link_to_function(result[:name],"setPosition(#{result[:lat]}, #{result[:lon]}, #{result[:zoom]})", html_options) if result[:name] diff --git a/app/models/diary_entry.rb b/app/models/diary_entry.rb index ad334151c..8894f4435 100644 --- a/app/models/diary_entry.rb +++ b/app/models/diary_entry.rb @@ -1,3 +1,8 @@ class DiaryEntry < ActiveRecord::Base belongs_to :user + + validates_presence_of :title, :body + validates_numericality_of :latitude, :allow_nil => true + validates_numericality_of :longitude, :allow_nil => true + validates_associated :user end diff --git a/app/models/message.rb b/app/models/message.rb index 039c8d30b..97e411192 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -1,4 +1,8 @@ class Message < ActiveRecord::Base belongs_to :sender, :class_name => "User", :foreign_key => :from_user_id belongs_to :recipient, :class_name => "User", :foreign_key => :to_user_id + + validates_presence_of :title, :body, :sent_on + validates_inclusion_of :message_read, :in => [ true, false ] + validates_associated :sender, :recipient end diff --git a/app/models/node.rb b/app/models/node.rb index 230c83882..7e78aaf59 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -68,18 +68,12 @@ class Node < ActiveRecord::Base return node end - def save_with_history - begin - Node.transaction do - self.timestamp = Time.now - self.save! - old_node = OldNode.from_node(self) - old_node.save! - end - - return true - rescue - return nil + def save_with_history! + Node.transaction do + self.timestamp = Time.now + self.save! + old_node = OldNode.from_node(self) + old_node.save! end end diff --git a/app/models/notifier.rb b/app/models/notifier.rb index aaad67d0e..9eff2fb92 100644 --- a/app/models/notifier.rb +++ b/app/models/notifier.rb @@ -37,4 +37,16 @@ class Notifier < ActionMailer::Base @body['trace_name'] = trace.name @body['error'] = error end + + def message_notification(message) + @recipients = message.recipient.email + @from = 'abuse@openstreetmap.org' + @subject = "[OpenStreetMap] #{message.sender.display_name} sent you a new message" + @body['to_user'] = message.recipient.display_name + @body['from_user'] = message.sender.display_name + @body['body'] = message.body + @body['subject'] = message.title + @body['readurl'] = "http://#{SERVER_URL}/message/read/#{message.id}" + @body['replyurl'] = "http://#{SERVER_URL}/message/new/#{message.from_user_id}" + end end diff --git a/app/models/relation.rb b/app/models/relation.rb index f74a149ec..a5d463ffb 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -141,46 +141,40 @@ class Relation < ActiveRecord::Base @tags[k] = v end - def save_with_history - begin - Relation.transaction do - t = Time.now - self.timestamp = t - self.save! - - tags = self.tags - - RelationTag.delete_all(['id = ?', self.id]) - - tags.each do |k,v| - tag = RelationTag.new - tag.k = k - tag.v = v - tag.id = self.id - tag.save! - end - - members = self.members + def save_with_history! + Relation.transaction do + t = Time.now + self.timestamp = t + self.save! + + tags = self.tags + + RelationTag.delete_all(['id = ?', self.id]) + + tags.each do |k,v| + tag = RelationTag.new + tag.k = k + tag.v = v + tag.id = self.id + tag.save! + end - RelationMember.delete_all(['id = ?', self.id]) + members = self.members - members.each do |n| - mem = RelationMember.new - mem.id = self.id - mem.member_type = n[0]; - mem.member_id = n[1]; - mem.member_role = n[2]; - mem.save! - end + RelationMember.delete_all(['id = ?', self.id]) - old_relation = OldRelation.from_relation(self) - old_relation.timestamp = t - old_relation.save_with_dependencies! + members.each do |n| + mem = RelationMember.new + mem.id = self.id + mem.member_type = n[0]; + mem.member_id = n[1]; + mem.member_role = n[2]; + mem.save! end - return true - rescue Exception => ex - return nil + old_relation = OldRelation.from_relation(self) + old_relation.timestamp = t + old_relation.save_with_dependencies! end end diff --git a/app/models/trace.rb b/app/models/trace.rb index c189c035e..4cac233c2 100644 --- a/app/models/trace.rb +++ b/app/models/trace.rb @@ -175,7 +175,12 @@ class Trace < ActiveRecord::Base f_lon = 0 first = true - Tracepoint.delete_all(['gpx_id = ?', self.id]) + # If there are any existing points for this trace then delete + # them - we check for existing points first to avoid locking + # the table in the common case where there aren't any. + if Tracepoint.exists?(['gpx_id = ?', self.id]) + Tracepoint.delete_all(['gpx_id = ?', self.id]) + end gpx.points do |point| if first @@ -199,10 +204,10 @@ class Trace < ActiveRecord::Base max_lon = Tracepoint.maximum('longitude', :conditions => ['gpx_id = ?', id]) min_lon = Tracepoint.minimum('longitude', :conditions => ['gpx_id = ?', id]) - max_lat = max_lat.to_f / 1000000 - min_lat = min_lat.to_f / 1000000 - max_lon = max_lon.to_f / 1000000 - min_lon = min_lon.to_f / 1000000 + max_lat = max_lat.to_f / 10000000 + min_lat = min_lat.to_f / 10000000 + max_lon = max_lon.to_f / 10000000 + min_lon = min_lon.to_f / 10000000 self.latitude = f_lat self.longitude = f_lon diff --git a/app/models/tracepoint.rb b/app/models/tracepoint.rb index 70d0f99e8..e0fcfbd97 100644 --- a/app/models/tracepoint.rb +++ b/app/models/tracepoint.rb @@ -1,26 +1,40 @@ class Tracepoint < ActiveRecord::Base -set_table_name 'gps_points' + set_table_name 'gps_points' -# validates_numericality_of :latitude -# validates_numericality_of :longitude + validates_numericality_of :trackid, :only_integer => true + validates_numericality_of :latitude, :only_integer => true + validates_numericality_of :longitude, :only_integer => true + validates_associated :trace + validates_presence_of :timestamp - belongs_to :user belongs_to :trace, :foreign_key => 'gpx_id' + + before_save :update_tile + + def self.find_by_area(minlat, minlon, maxlat, maxlon, options) + self.with_scope(:find => {:conditions => OSM.sql_for_area(minlat, minlon, maxlat, maxlon)}) do + return self.find(:all, options) + end + end + + def update_tile + self.tile = QuadTile.tile_for_point(lat, lon) + end def lat=(l) - self.latitude = l * 1000000 + self.latitude = (l * 10000000).round end def lng=(l) - self.longitude = l * 1000000 + self.longitude = (l * 10000000).round end def lat - return self.latitude.to_f / 1000000 + return self.latitude.to_f / 10000000 end def lon - return self.longitude.to_f / 1000000 + return self.longitude.to_f / 10000000 end def to_xml_node @@ -29,5 +43,4 @@ set_table_name 'gps_points' el1['lon'] = self.lon.to_s return el1 end - end diff --git a/app/models/way.rb b/app/models/way.rb index b564a3317..e0a445074 100644 --- a/app/models/way.rb +++ b/app/models/way.rb @@ -142,49 +142,47 @@ class Way < ActiveRecord::Base @tags[k] = v end - def save_with_history - begin - Way.transaction do - t = Time.now - self.timestamp = t - self.save! + def save_with_history! + t = Time.now - tags = self.tags + Way.transaction do + self.timestamp = t + self.save! + end - WayTag.delete_all(['id = ?', self.id]) + WayTag.transaction do + tags = self.tags - tags.each do |k,v| - tag = WayTag.new - tag.k = k - tag.v = v - tag.id = self.id - tag.save! - end + WayTag.delete_all(['id = ?', self.id]) - nds = self.nds + tags.each do |k,v| + tag = WayTag.new + tag.k = k + tag.v = v + tag.id = self.id + tag.save! + end + end - WayNode.delete_all(['id = ?', self.id]) + WayNode.transaction do + nds = self.nds - i = 1 - nds.each do |n| - nd = WayNode.new - nd.id = self.id - nd.node_id = n - nd.sequence_id = i - nd.save! - i += 1 - end + WayNode.delete_all(['id = ?', self.id]) - old_way = OldWay.from_way(self) - old_way.timestamp = t - old_way.save_with_dependencies! + i = 1 + nds.each do |n| + nd = WayNode.new + nd.id = self.id + nd.node_id = n + nd.sequence_id = i + nd.save! + i += 1 end - - return true - rescue => ex - puts ex - return nil end + + old_way = OldWay.from_way(self) + old_way.timestamp = t + old_way.save_with_dependencies! end def preconditions_ok? diff --git a/app/views/diary_entry/_diary_entry.rhtml b/app/views/diary_entry/_diary_entry.rhtml index 168bb832b..366a67f0e 100644 --- a/app/views/diary_entry/_diary_entry.rhtml +++ b/app/views/diary_entry/_diary_entry.rhtml @@ -1,5 +1,8 @@ <%= diary_entry.title %>
<%= simple_format(diary_entry.body) %> -Posted by user <%= link_to diary_entry.user.display_name, :controller => 'user', :action => 'view', :display_name => diary_entry.user.display_name %> at <%= diary_entry.created_at %>
+<% if diary_entry.latitude and diary_entry.longitude %> +Coordinates:
<%= diary_entry.latitude %>; <%= diary_entry.longitude %>
(<%=link_to 'map', :controller => 'site', :action => 'index', :lat => diary_entry.latitude, :lon => diary_entry.longitude, :zoom => 14 %> / <%=link_to 'edit', :controller => 'site', :action => 'edit', :lat => diary_entry.latitude, :lon => diary_entry.longitude, :zoom => 14 %>)
+<% end %> +Posted by <%= link_to diary_entry.user.display_name, :controller => 'user', :action => 'view', :display_name => diary_entry.user.display_name %> at <%= diary_entry.created_at %>


diff --git a/app/views/diary_entry/list.rhtml b/app/views/diary_entry/list.rhtml index 8a60c1863..a7aa84c6f 100644 --- a/app/views/diary_entry/list.rhtml +++ b/app/views/diary_entry/list.rhtml @@ -1,7 +1,11 @@ <% if @this_user %>

<%= @this_user.display_name %>'s diary

- - <% if @user and @this_user.id == @user.id %> + <% if @user == @this_user %> + <%= link_to 'New diary post', :controller => 'diary_entry', :action => 'new', :display_name => @user.display_name %> + <% end %> +<% else %> +

Users' diaries

+ <% if @user %> <%= link_to 'New diary post', :controller => 'diary_entry', :action => 'new', :display_name => @user.display_name %> <% end %> <% end %> diff --git a/app/views/diary_entry/new.rhtml b/app/views/diary_entry/new.rhtml index 16974fad2..69995d00e 100644 --- a/app/views/diary_entry/new.rhtml +++ b/app/views/diary_entry/new.rhtml @@ -10,9 +10,62 @@ Body <%= f.text_area :body, :cols => 80 %> + + Location + + Latitude: <%= f.text_field :latitude, :size => 20, :id => "latitude" %> Longitude: <%= f.text_field :longitude, :size => 20, :id => "longitude" %> use map + <%= submit_tag 'Save' %> <% end %> + +<% if @user.home_lat.nil? or @user.home_lon.nil? %> + <% lon = params['lon'] || '-0.1' %> + <% lat = params['lat'] || '51.5' %> + <% zoom = params['zoom'] || '4' %> +<% else %> + <% lon = @user.home_lon %> + <% lat = @user.home_lat %> + <% zoom = '12' %> +<% end %> + + +<%= javascript_include_tag 'map.js' %> + + \ No newline at end of file diff --git a/app/views/message/_message_summary.rhtml b/app/views/message/_message_summary.rhtml index 56f6bb132..02972728e 100644 --- a/app/views/message/_message_summary.rhtml +++ b/app/views/message/_message_summary.rhtml @@ -1,7 +1,9 @@ +<% this_colour = cycle('lightgrey', 'white') # can only call once for some dumb reason %> + "> - <%= link_to message_summary.sender.display_name , :controller => 'user', :action => message_summary.sender.display_name %> - <%= link_to message_summary.title , :controller => 'message', :action => 'read', :message_id => message_summary.id %> - <%= message_summary.sent_on %> + <%= link_to message_summary.sender.display_name , :controller => 'user', :action => message_summary.sender.display_name %> + <%= link_to message_summary.title , :controller => 'message', :action => 'read', :message_id => message_summary.id %> + <%= message_summary.sent_on %> <% if message_summary.message_read? %> <%= button_to 'Mark as unread', :controller => 'message', :action => 'mark', :message_id => message_summary.id, :mark => 'unread' %> <% else %> diff --git a/app/views/message/read.rhtml b/app/views/message/read.rhtml index b84fea4c7..7a0d2bbe1 100644 --- a/app/views/message/read.rhtml +++ b/app/views/message/read.rhtml @@ -2,19 +2,19 @@ - + - + - + - +
FromFrom <%= link_to @message.sender.display_name, :controller => 'user', :action => 'view', :display_name => @message.sender.display_name %>
SubjectSubject <%= @message.title %>
DateDate <%= @message.sent_on %>
Message <%= @message.body %>
diff --git a/app/views/notifier/message_notification.rhtml b/app/views/notifier/message_notification.rhtml new file mode 100644 index 000000000..892ac11c0 --- /dev/null +++ b/app/views/notifier/message_notification.rhtml @@ -0,0 +1,10 @@ +Hi <%= @to_user %>, + +<%= @from_user %> has sent you a message through OpenStreetMap with the subject "<%= @subject %>": + +== +<%= @body %> +== + +You can also read the message at <%= @readurl %> +and you can reply at <%= @replyurl %> diff --git a/app/views/site/_search.rhtml b/app/views/site/_search.rhtml index 14f8fa5f6..84f44f0f4 100644 --- a/app/views/site/_search.rhtml +++ b/app/views/site/_search.rhtml @@ -66,7 +66,7 @@

examples: 'Alkmaar', 'Regent Street, Cambridge', 'CB2 5AQ', or 'post offices near Lünen' - more examples... + more examples...

<% end %> diff --git a/app/views/site/edit.rhtml b/app/views/site/edit.rhtml index a41a80176..b1c555586 100644 --- a/app/views/site/edit.rhtml +++ b/app/views/site/edit.rhtml @@ -39,10 +39,12 @@ var fo = new SWFObject("/potlatch/potlatch.swf?d="+Math.round(Math.random()*1000), "potlatch", "700", "600", "6", "#FFFFFF"); function doSWF(lat,lon,sc) { + if (sc < 11) sc = 11; fo.addVariable('lat',lat); fo.addVariable('long',lon); fo.addVariable('scale',sc); fo.addVariable('token','<%= session[:token] %>'); +<% if params['gpx'] %> fo.addVariable('gpx','<%= params['gpx']+"/data" %>'); <% end %> fo.write("map"); } diff --git a/app/views/site/index.rhtml b/app/views/site/index.rhtml index 41b2b86f2..bbd1a8a77 100644 --- a/app/views/site/index.rhtml +++ b/app/views/site/index.rhtml @@ -88,14 +88,14 @@ map.setCenter(centre, zoom); <% end %> - <% if marker %> - marker = addMarkerToMap(lonLatToMercator(new OpenLayers.LonLat(<%= mlon %>, <%= mlat %>))); - <% end %> - <% if layers %> setMapLayers("<%= layers %>"); <% end %> + <% if marker %> + marker = addMarkerToMap(lonLatToMercator(new OpenLayers.LonLat(<%= mlon %>, <%= mlat %>))); + <% end %> + map.events.register("moveend", map, updateLocation); updateLocation(); diff --git a/app/views/trace/_trace.rhtml b/app/views/trace/_trace.rhtml index eb8558510..91862444a 100644 --- a/app/views/trace/_trace.rhtml +++ b/app/views/trace/_trace.rhtml @@ -15,7 +15,7 @@ ... <%= time_ago_in_words( trace.timestamp ) %> ago <%= link_to 'more', {:controller => 'trace', :action => 'view', :display_name => trace.user.display_name, :id => trace.id}, {:title => 'View Trace Details'} %> / <%= link_to_if trace.inserted?, 'map', {:controller => 'site', :action => 'index', :lat => trace.latitude, :lon => trace.longitude, :zoom => 14}, {:title => 'View Map'} %> / - <%= link_to_if trace.inserted?, 'edit', {:controller => 'site', :action => 'edit', :lat => trace.latitude, :lon => trace.longitude, :zoom => 14}, {:title => 'Edit Map'} %> + <%= link_to_if trace.inserted?, 'edit', {:controller => 'site', :action => 'edit', :lat => trace.latitude, :lon => trace.longitude, :zoom => 14, :gpx => trace.id }, {:title => 'Edit Map'} %>
<%= escape_once(trace.description) %>
diff --git a/app/views/trace/view.rhtml b/app/views/trace/view.rhtml index 1ad563729..60f71b7c7 100644 --- a/app/views/trace/view.rhtml +++ b/app/views/trace/view.rhtml @@ -17,7 +17,7 @@ <%= @trace.size.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,') %> Start coordinate: - <%= @trace.latitude %>, <%= @trace.longitude %> (<%=link_to 'map', :controller => 'site', :action => 'index', :lat => @trace.latitude, :lon => @trace.longitude, :zoom => 14 %> / <%=link_to 'edit', :controller => 'site', :action => 'edit', :lat => @trace.latitude, :lon => @trace.longitude, :zoom => 14 %>) +
<%= @trace.latitude %>; <%= @trace.longitude %>
(<%=link_to 'map', :controller => 'site', :action => 'index', :lat => @trace.latitude, :lon => @trace.longitude, :zoom => 14 %> / <%=link_to 'edit', :controller => 'site', :action => 'edit', :lat => @trace.latitude, :lon => @trace.longitude, :gpx=> @trace.id, :zoom => 14 %>) <% end %> diff --git a/config/environment.rb b/config/environment.rb index 570cb04b5..3820ed294 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,8 @@ # Be sure to restart your web server when you modify this file. +# Limit each rails process to a 512Mb resident set size +Process.setrlimit Process::RLIMIT_AS, 640*1024*1024, Process::RLIM_INFINITY + # Uncomment below to force Rails into production mode when # you don't control web/app server and can't set it the proper way ENV['RAILS_ENV'] ||= 'production' diff --git a/db/README b/db/README index e3e210a43..f4530f090 100644 --- a/db/README +++ b/db/README @@ -22,10 +22,33 @@ $ mysql -u -p > flush privileges; > exit +Creating functions +==================== + +Run this command in the db/functions directory: + +$ make + +Make sure the db/functions directory is on the MySQL server's library +path and restart the MySQL server. On linux the easiest way to do this +is to create /etc/ld.so.conf.d/osm.conf and place the path to the +db/functions directory in it and then run the following command as root: + +$ ldconfig + +Now create the functions as follows: + +$ mysql -u -p openstreetmap + +(change with appropriate username of administrative user eg. root ) + +> create function tile_for_point returns integer soname 'libquadtile.so'; +> exit + Creating database skeleton tables =================================== -Run this command from the root of your rails direcotry: +Run this command from the root of your rails directory: $ rake db:migrate diff --git a/db/functions/Makefile b/db/functions/Makefile new file mode 100644 index 000000000..6544db1ff --- /dev/null +++ b/db/functions/Makefile @@ -0,0 +1,4 @@ +QTDIR=../../lib/quad_tile + +libquadtile.so: quadtile.c ${QTDIR}/quad_tile.h + cc `mysql_config --include` -I${QTDIR} -fPIC -O3 -shared -o libquadtile.so quadtile.c diff --git a/db/functions/quadtile.c b/db/functions/quadtile.c new file mode 100644 index 000000000..d60189245 --- /dev/null +++ b/db/functions/quadtile.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +my_bool tile_for_point_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if ( args->arg_count != 2 || + args->arg_type[0] != INT_RESULT || + args->arg_type[1] != INT_RESULT ) + { + strcpy( message, "Your tile_for_point arguments are bogus!" ); + return 1; + } + + return 0; +} + +void tile_for_point_deinit(UDF_INIT *initid) +{ + return; +} + +long long tile_for_point(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) +{ + long long lat = *(long long *)args->args[0]; + long long lon = *(long long *)args->args[1]; + + return xy2tile(lon2x(lon / 10000000.0), lat2y(lat / 10000000.0)); +} diff --git a/db/migrate/005_tile_tracepoints.rb b/db/migrate/005_tile_tracepoints.rb new file mode 100644 index 000000000..c0e6d8a61 --- /dev/null +++ b/db/migrate/005_tile_tracepoints.rb @@ -0,0 +1,15 @@ +class TileTracepoints < ActiveRecord::Migration + def self.up + add_column "gps_points", "tile", :integer, :null => false, :unsigned => true + add_index "gps_points", ["tile"], :name => "points_tile_idx" + remove_index "gps_points", :name => "points_idx" + + Tracepoint.update_all("latitude = latitude * 10, longitude = longitude * 10, tile = tile_for_point(latitude * 10, longitude * 10)") + end + + def self.down + add_index "gps_points", ["latitude", "longitude"], :name => "points_idx" + remove_index "gps_points", :name => "points_tile_idx" + remove_column "gps_points", "tile" + end +end diff --git a/db/migrate/005_add_relations.rb b/db/migrate/006_add_relations.rb similarity index 100% rename from db/migrate/005_add_relations.rb rename to db/migrate/006_add_relations.rb diff --git a/db/migrate/006_remove_segments.rb b/db/migrate/007_remove_segments.rb similarity index 96% rename from db/migrate/006_remove_segments.rb rename to db/migrate/007_remove_segments.rb index de9557cc9..492beda63 100644 --- a/db/migrate/006_remove_segments.rb +++ b/db/migrate/007_remove_segments.rb @@ -5,9 +5,9 @@ class RemoveSegments < ActiveRecord::Migration have_segs = select_value("SELECT count(*) FROM current_segments").to_i != 0 if have_segs - prefix = File.join Dir.tmpdir, "006_remove_segments.#{$$}." + prefix = File.join Dir.tmpdir, "007_remove_segments.#{$$}." - cmd = "db/migrate/006_remove_segments_helper" + cmd = "db/migrate/007_remove_segments_helper" src = "#{cmd}.cc" if not File.exists? cmd or File.mtime(cmd) < File.mtime(src) then system 'c++ -O3 -Wall `mysql_config --cflags --libs` ' + diff --git a/db/migrate/006_remove_segments_helper.cc b/db/migrate/007_remove_segments_helper.cc similarity index 97% rename from db/migrate/006_remove_segments_helper.cc rename to db/migrate/007_remove_segments_helper.cc index dd2176a04..2234a3bb5 100644 --- a/db/migrate/006_remove_segments_helper.cc +++ b/db/migrate/007_remove_segments_helper.cc @@ -32,9 +32,9 @@ static T parse(const char *str) { static void exit_mysql_err(MYSQL *mysql) { const char *err = mysql_error(mysql); if (err) { - fprintf(stderr, "005_remove_segments_helper: MySQL error: %s\n", err); + fprintf(stderr, "007_remove_segments_helper: MySQL error: %s\n", err); } else { - fprintf(stderr, "005_remove_segments_helper: MySQL error\n"); + fprintf(stderr, "007_remove_segments_helper: MySQL error\n"); } abort(); exit(EXIT_FAILURE); @@ -43,9 +43,9 @@ static void exit_mysql_err(MYSQL *mysql) { static void exit_stmt_err(MYSQL_STMT *stmt) { const char *err = mysql_stmt_error(stmt); if (err) { - fprintf(stderr, "005_remove_segments_helper: MySQL stmt error: %s\n", err); + fprintf(stderr, "007_remove_segments_helper: MySQL stmt error: %s\n", err); } else { - fprintf(stderr, "005_remove_segments_helper: MySQL stmt error\n"); + fprintf(stderr, "007_remove_segments_helper: MySQL stmt error\n"); } abort(); exit(EXIT_FAILURE); @@ -536,7 +536,7 @@ int main(int argc, char **argv) { char *tempfn; if (argc != 8) { - printf("Usage: 006_remove_segments_helper host user passwd database port socket prefix\n"); + printf("Usage: 007_remove_segments_helper host user passwd database port socket prefix\n"); exit(EXIT_FAILURE); } diff --git a/lib/migrate.rb b/lib/migrate.rb index c31e31538..1d32d175d 100644 --- a/lib/migrate.rb +++ b/lib/migrate.rb @@ -17,6 +17,14 @@ module ActiveRecord return false if options[:options] =~ /AUTO_INCREMENT/i return old_options_include_default?(options) end + + alias_method :old_add_column_options!, :add_column_options! + + def add_column_options!(sql, options) + sql << " UNSIGNED" if options[:unsigned] + old_add_column_options!(sql, options) + sql << " #{options[:options]}" + end end class MysqlAdapter @@ -40,7 +48,6 @@ module ActiveRecord change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" add_column_options!(change_column_sql, options) - change_column_sql << " #{options[:options]}" execute(change_column_sql) end diff --git a/lib/osm.rb b/lib/osm.rb index aab3e1335..45c506e2e 100644 --- a/lib/osm.rb +++ b/lib/osm.rb @@ -410,4 +410,15 @@ module OSM return Digest::MD5.hexdigest(password) if salt.nil? return Digest::MD5.hexdigest(salt + password) end + + # Return an SQL fragment to select a given area of the globe + def self.sql_for_area(minlat, minlon, maxlat, maxlon, prefix = nil) + tilesql = QuadTile.sql_for_area(minlat, minlon, maxlat, maxlon, prefix) + minlat = (minlat * 10000000).round + minlon = (minlon * 10000000).round + maxlat = (maxlat * 10000000).round + maxlon = (maxlon * 10000000).round + + return "#{tilesql} AND #{prefix}latitude BETWEEN #{minlat} AND #{maxlat} AND #{prefix}longitude BETWEEN #{minlon} AND #{maxlon}" + end end diff --git a/lib/quad_tile.rb b/lib/quad_tile.rb new file mode 100644 index 000000000..6e4fb6d22 --- /dev/null +++ b/lib/quad_tile.rb @@ -0,0 +1,81 @@ +module QuadTile + begin + require "quad_tile/quad_tile_so" + rescue MissingSourceFile + def self.tile_for_point(lat, lon) + x = ((lon + 180) * 65535 / 360).round + y = ((lat + 90) * 65535 / 180).round + + return tile_for_xy(x, y) + end + + def self.tiles_for_area(minlat, minlon, maxlat, maxlon) + minx = ((minlon + 180) * 65535 / 360).round + maxx = ((maxlon + 180) * 65535 / 360).round + miny = ((minlat + 90) * 65535 / 180).round + maxy = ((maxlat + 90) * 65535 / 180).round + tiles = [] + + minx.upto(maxx) do |x| + miny.upto(maxy) do |y| + tiles << tile_for_xy(x, y) + end + end + + return tiles + end + + def self.tile_for_xy(x, y) + t = 0 + + 16.times do + t = t << 1 + t = t | 1 unless (x & 0x8000).zero? + x <<= 1 + t = t << 1 + t = t | 1 unless (y & 0x8000).zero? + y <<= 1 + end + + return t + end + end + + def self.sql_for_area(minlat, minlon, maxlat, maxlon, prefix) + sql = Array.new + single = Array.new + + iterate_tiles_for_area(minlat, minlon, maxlat, maxlon) do |first,last| + if first == last + single.push(first) + else + sql.push("#{prefix}tile BETWEEN #{first} AND #{last}") + end + end + + sql.push("#{prefix}tile IN (#{single.join(',')})") if single.size > 0 + + return "( " + sql.join(" OR ") + " )" + end + + def self.iterate_tiles_for_area(minlat, minlon, maxlat, maxlon) + tiles = tiles_for_area(minlat, minlon, maxlat, maxlon) + first = last = nil + + tiles.sort.each do |tile| + if last.nil? + first = last = tile + elsif tile == last + 1 + last = tile + else + yield first, last + + first = last = tile + end + end + + yield first, last unless last.nil? + end + + private_class_method :tile_for_xy, :iterate_tiles_for_area +end diff --git a/lib/quad_tile/extconf.rb b/lib/quad_tile/extconf.rb new file mode 100644 index 000000000..c7fc1b899 --- /dev/null +++ b/lib/quad_tile/extconf.rb @@ -0,0 +1,3 @@ +require "mkmf" + +create_makefile("quad_tile_so") diff --git a/lib/quad_tile/quad_tile.c b/lib/quad_tile/quad_tile.c new file mode 100644 index 000000000..137963bd0 --- /dev/null +++ b/lib/quad_tile/quad_tile.c @@ -0,0 +1,47 @@ +#include "ruby.h" +#include "quad_tile.h" + +static VALUE tile_for_point(VALUE self, VALUE lat, VALUE lon) +{ + unsigned int x = lon2x(NUM2DBL(lon)); + unsigned int y = lat2y(NUM2DBL(lat)); + + return UINT2NUM(xy2tile(x, y)); +} + +static VALUE tiles_for_area(VALUE self, VALUE minlat, VALUE minlon, VALUE maxlat, VALUE maxlon) +{ + unsigned int minx = lon2x(NUM2DBL(minlon)); + unsigned int maxx = lon2x(NUM2DBL(maxlon)); + unsigned int miny = lat2y(NUM2DBL(minlat)); + unsigned int maxy = lat2y(NUM2DBL(maxlat)); + VALUE tiles = rb_ary_new(); + unsigned int x; + unsigned int y; + + for (x = minx; x <= maxx; x++) + { + for (y = miny; y <= maxy; y++) + { + rb_ary_push(tiles, UINT2NUM(xy2tile(x, y))); + } + } + + return tiles; +} + +static VALUE tile_for_xy(VALUE self, VALUE x, VALUE y) +{ + return UINT2NUM(xy2tile(NUM2UINT(x), NUM2UINT(y))); +} + +void Init_quad_tile_so(void) +{ + VALUE m = rb_define_module("QuadTile"); + + rb_define_module_function(m, "tile_for_point", tile_for_point, 2); + rb_define_module_function(m, "tiles_for_area", tiles_for_area, 4); + rb_define_module_function(m, "tile_for_xy", tile_for_xy, 2); + + return; +} diff --git a/lib/quad_tile/quad_tile.h b/lib/quad_tile/quad_tile.h new file mode 100644 index 000000000..f868ff515 --- /dev/null +++ b/lib/quad_tile/quad_tile.h @@ -0,0 +1,25 @@ +#include + +inline unsigned int xy2tile(unsigned int x, unsigned int y) +{ + unsigned int tile = 0; + int i; + + for (i = 15; i >= 0; i--) + { + tile = (tile << 1) | ((x >> i) & 1); + tile = (tile << 1) | ((y >> i) & 1); + } + + return tile; +} + +inline unsigned int lon2x(double lon) +{ + return round((lon + 180.0) * 65535.0 / 360.0); +} + +inline unsigned int lat2y(double lat) +{ + return round((lat + 90.0) * 65535.0 / 180.0); +} diff --git a/public/potlatch/potlatch.swf b/public/potlatch/potlatch.swf index 28db77cc4..ce4cd00a4 100755 Binary files a/public/potlatch/potlatch.swf and b/public/potlatch/potlatch.swf differ diff --git a/public/potlatch/ymap.swf b/public/potlatch/ymap.swf index 10242b7c0..873fc3ed2 100755 Binary files a/public/potlatch/ymap.swf and b/public/potlatch/ymap.swf differ diff --git a/test/fixtures/current_relation_members.yml b/test/fixtures/current_relation_members.yml index 7921ac145..bddc8a0dd 100644 --- a/test/fixtures/current_relation_members.yml +++ b/test/fixtures/current_relation_members.yml @@ -1,5 +1,23 @@ t1: + id: 1 + member_role: "some" + member_type: "way" + member_id: 3 + +t2: id: 1 member_role: "some" member_type: "node" + member_id: 5 + +t3: + id: 1 + member_role: "some" + member_type: "relation" member_id: 3 + +t4: + id: 3 + member_role: "some" + member_type: "node" + member_id: 5 diff --git a/test/fixtures/current_relation_tags.yml b/test/fixtures/current_relation_tags.yml index ba795b698..aaf06a397 100644 --- a/test/fixtures/current_relation_tags.yml +++ b/test/fixtures/current_relation_tags.yml @@ -7,3 +7,8 @@ t2: id: 2 k: test v: yes + +t2: + id: 3 + k: test + v: yes diff --git a/test/fixtures/current_relations.yml b/test/fixtures/current_relations.yml index 67c8ddb95..c1f77d428 100644 --- a/test/fixtures/current_relations.yml +++ b/test/fixtures/current_relations.yml @@ -9,3 +9,9 @@ invisible_relation: user_id: 1 timestamp: 2007-01-01 00:00:00 visible: 0 + +used_relation: + id: 3 + user_id: 1 + timestamp: 2007-01-01 00:00:00 + visible: 1 diff --git a/test/fixtures/relation_members.yml b/test/fixtures/relation_members.yml index f424e6a51..27e8b533a 100644 --- a/test/fixtures/relation_members.yml +++ b/test/fixtures/relation_members.yml @@ -1,6 +1,24 @@ t1: + id: 1 + member_role: "some" + member_type: "way" + member_id: 3 + version: 1 +t2: id: 1 member_role: "some" member_type: "node" + member_id: 5 + version: 1 +t3: + id: 1 + member_role: "some" + member_type: "relation" member_id: 3 version: 1 +t4: + id: 3 + member_role: "some" + member_type: "node" + member_id: 5 + version: 1 diff --git a/test/fixtures/relation_tags.yml b/test/fixtures/relation_tags.yml index d1c69a6d4..39f4bd5de 100644 --- a/test/fixtures/relation_tags.yml +++ b/test/fixtures/relation_tags.yml @@ -9,3 +9,9 @@ t2: k: test v: yes version: 1 + +t3: + id: 3 + k: test + v: yes + version: 1 diff --git a/test/fixtures/relations.yml b/test/fixtures/relations.yml index f1e4026ff..cf1d1ff56 100644 --- a/test/fixtures/relations.yml +++ b/test/fixtures/relations.yml @@ -11,3 +11,10 @@ invisible_relation: timestamp: 2007-01-01 00:00:00 visible: 0 version: 1 + +used_relation: + id: 3 + user_id: 1 + timestamp: 2007-01-01 00:00:00 + visible: 1 + version: 1 diff --git a/test/functional/relation_controller_test.rb b/test/functional/relation_controller_test.rb index 2893ba956..8f8b72770 100644 --- a/test/functional/relation_controller_test.rb +++ b/test/functional/relation_controller_test.rb @@ -42,7 +42,7 @@ class RelationControllerTest < Test::Unit::TestCase assert_response :not_found # check the "relations for node" mode - get :relations_for_node, :id => current_nodes(:used_node_1).id + get :relations_for_node, :id => current_nodes(:node_used_by_relationship).id assert_response :success # FIXME check whether this contains the stuff we want! if $VERBOSE @@ -59,7 +59,7 @@ class RelationControllerTest < Test::Unit::TestCase # check the "relations for relation" mode - get :relations_for_node, :id => current_relations(:used_relation).id + get :relations_for_relation, :id => current_relations(:used_relation).id assert_response :success # FIXME check whether this contains the stuff we want! if $VERBOSE @@ -67,7 +67,7 @@ class RelationControllerTest < Test::Unit::TestCase end # check the "full" mode - get :full, :id => current_relations(:relation_using_all).id + get :full, :id => current_relations(:visible_relation).id assert_response :success # FIXME check whether this contains the stuff we want! if $VERBOSE diff --git a/test/unit/node_test.rb b/test/unit/node_test.rb index b3e834370..95321b5cf 100644 --- a/test/unit/node_test.rb +++ b/test/unit/node_test.rb @@ -11,7 +11,7 @@ class NodeTest < Test::Unit::TestCase :user_id => users(:normal_user).id, :visible => 1, :tags => "") - assert node_template.save_with_history + assert node_template.save_with_history! node = Node.find(node_template.id) assert_not_nil node @@ -44,7 +44,7 @@ class NodeTest < Test::Unit::TestCase node_template.latitude = 12.3456 node_template.longitude = 65.4321 node_template.tags = "updated=yes" - assert node_template.save_with_history + assert node_template.save_with_history! node = Node.find(node_template.id) assert_not_nil node @@ -76,7 +76,7 @@ class NodeTest < Test::Unit::TestCase assert_not_nil old_node_template node_template.visible = 0 - assert node_template.save_with_history + assert node_template.save_with_history! node = Node.find(node_template.id) assert_not_nil node