- # ----- whichways
- # Find all the way ids and nodes (including tags and projected lat/lng) which aren't part of those ways in an are
- #
- # The argument is an array containing the following, in order:
- # 0. minimum longitude
- # 1. minimum latitude
- # 2. maximum longitude
- # 3. maximum latitude
- # 4. baselong, 5. basey, 6. masterscale as above
- def whichways(args) #:doc:
- xmin = args[0].to_f-0.01
- 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}")
-
- # find the way ids in an area
- nodes_in_area = Node.find_by_area(ymin, xmin, ymax, xmax, :conditions => "current_nodes.visible = 1", :include => :ways)
- way_ids = nodes_in_area.collect { |node| node.way_ids }.flatten.uniq
-
- # find the node ids in an area that aren't part of ways
- nodes_not_used_in_area = nodes_in_area.select { |node| node.ways.empty? }
- points = nodes_not_used_in_area.collect { |n| [n.id, n.lon_potlatch(baselong,masterscale), n.lat_potlatch(basey,masterscale), n.tags_as_hash] }
-
- [way_ids,points]
- end
-
- # ----- whichways_deleted
- # return array of deleted ways in current bounding box
- # in: as whichways
- # does: finds all deleted ways with a deleted node in bounding box
- # out: [0] array of way ids
- def whichways_deleted(args) #:doc:
- xmin = args[0].to_f-0.01
- 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]
-
- sql=<<-EOF
- SELECT DISTINCT current_ways.id
- FROM current_nodes,way_nodes,current_ways
- WHERE #{OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")}
- AND way_nodes.node_id=current_nodes.id
- AND way_nodes.id=current_ways.id
- AND current_nodes.visible=0
- AND current_ways.visible=0
- EOF
- waylist = ActiveRecord::Base.connection.select_all(sql)
- ways = waylist.collect {|a| a['id'].to_i }
- [ways]
- end
-
- # ----- getway
- # Get a way with all of it's nodes and tags
- # The input is an array with the following components, in order:
- # 0. wayid - the ID of the way to get
- # 1. baselong - origin of SWF map (longitude)
- # 2. basey - origin of SWF map (latitude)
- # 3. masterscale - SWF map scale
- #
- # The output is an array which contains all the nodes (with projected
- # latitude and longitude) and tags for a way (and all the nodes tags).
- # It also has the way's unprojected (WGS84) bbox.
- #
- # FIXME: The server really shouldn't be figuring out a ways bounding box and doing projection for potlatch
- # FIXME: the argument splitting should be done in the 'talk' method, not here
- def getway(args) #:doc:
- wayid,baselong,basey,masterscale = args
- wayid = wayid.to_i
-
- RAILS_DEFAULT_LOGGER.info(" Message: getway, id=#{wayid}")
-
- # Ideally we would do ":include => :nodes" here but if we do that
- # then rails only seems to return the first copy of a node when a
- # way includes a node more than once
- way = Way.find(wayid)
-
- long_array = []
- lat_array = []
- points = []
-
- way.nodes.each do |node|
- projected_longitude = node.lon_potlatch(baselong,masterscale) # do projection for potlatch
- projected_latitude = node.lat_potlatch(basey,masterscale)
- id = node.id
- tags_hash = node.tags_as_hash
-
- points << [projected_longitude, projected_latitude, id, nil, tags_hash]
- long_array << projected_longitude
- lat_array << projected_latitude
- end
-
- [wayid,points,way.tags,long_array.min,long_array.max,lat_array.min,lat_array.max]
- end
-
- # ----- getway_old
- # returns old version of way
- # in: [0] way id,
- # [1] way version to get (or -1 for "last deleted version")
- # [2] baselong, [3] basey, [4] masterscale
- # does: gets old version of way and all constituent nodes
- # for undelete, always uses the most recent version of each node
- # (even if it's moved)
- # for revert, uses the historic version of each node, but if that node is
- # still visible and has been changed since, generates a new node id
- # out: [0] 0 (code for success), [1] SWF object name,
- # [2] array of points (as getway _except_ [3] is node.visible?, 0 or 1),
- # [4] xmin, [5] xmax, [6] ymin, [7] ymax (unprojected bbox),
- # [8] way version
- def getway_old(args) #:doc:
- RAILS_DEFAULT_LOGGER.info(" Message: getway_old (server is #{SERVER_URL})")
- # if SERVER_URL=="www.openstreetmap.org" then return -1,"Revert is not currently enabled on the OpenStreetMap server." end
-
- wayid,version,baselong,basey,masterscale=args
- wayid = wayid.to_i
- version = version.to_i
- xmin = ymin = 999999
- xmax = ymax = -999999
- points=[]
- if version<0
- historic=false
- version=getlastversion(wayid,version)
- else
- historic=true
- end
- readwayquery_old(wayid,version,historic).each { |row|
- points<<[long2coord(row['longitude'].to_f,baselong,masterscale),lat2coord(row['latitude'].to_f,basey,masterscale),row['id'].to_i,row['visible'].to_i,tag2array(row['tags'].to_s)]
- xmin=[xmin,row['longitude'].to_f].min
- xmax=[xmax,row['longitude'].to_f].max
- ymin=[ymin,row['latitude' ].to_f].min
- ymax=[ymax,row['latitude' ].to_f].max
- }
-
- # get tags from this version
- attributes={}
- attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM way_tags WHERE id=#{wayid} AND version=#{version}"
- attrlist.each {|a| attributes[a['k'].gsub(':','|')]=a['v'] }
- attributes['history']="Retrieved from v"+version.to_s
-
- [0,wayid,points,attributes,xmin,xmax,ymin,ymax,version]
- end
-
- # ----- getway_history
- # find history of a way
- # in: [0] way id
- # does: finds history of a way
- # out: [0] array of previous versions (where each is
- # [0] version, [1] db timestamp (string),
- # [2] visible 0 or 1,
- # [3] username or 'anonymous' (string))
- def getway_history(args) #:doc:
- wayid=args[0]
- history=[]
- sql=<<-EOF
- SELECT version,timestamp,visible,display_name,data_public
- FROM ways,users
- WHERE ways.id=#{wayid}
- AND ways.user_id=users.id
- AND ways.visible=1
- ORDER BY version DESC
- EOF
- histlist=ActiveRecord::Base.connection.select_all(sql)
- histlist.each { |row|
- if row['data_public'].to_i==1 then user=row['display_name'] else user='anonymous' end
- history<<[row['version'],row['timestamp'],row['visible'],user]
- }
- [history]
- end
-
- # ----- putway
- # saves a way to the database
- # in: [0] user token (string),
- # [1] original way id (may be negative),
- # [2] array of points (as getway/getway_old),
- # [3] hash of way tags,
- # [4] original way version (0 if not a reverted/undeleted way),
- # [5] baselong, [6] basey, [7] masterscale
- # does: saves way to the database
- # all constituent nodes are created/updated as necessary
- # (or deleted if they were in the old version and are otherwise unused)
- # out: [0] 0 (code for success), [1] original way id (unchanged),
- # [2] new way id, [3] hash of renumbered nodes (old id=>new id),
- # [4] xmin, [5] xmax, [6] ymin, [7] ymax (unprojected bbox)
- def putway(args,renumberednodes) #:doc:
- RAILS_DEFAULT_LOGGER.info(" putway started")
- usertoken,originalway,points,attributes,oldversion,baselong,basey,masterscale=args
- uid=getuserid(usertoken)
- if !uid then return -1,"You are not logged in, so the way could not be saved." end
-
- RAILS_DEFAULT_LOGGER.info(" putway authenticated happily")
- db_uqn='unin'+(rand*100).to_i.to_s+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquenodes table name, typically 51 chars
- db_now='@now'+(rand*100).to_i.to_s+uid.to_s+originalway.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()")
- originalway=originalway.to_i
- oldversion=oldversion.to_i
-
- RAILS_DEFAULT_LOGGER.info(" Message: putway, id=#{originalway}")
-
- # -- Check for null IDs or short ways
-
- points.each do |a|
- if a[2]==0 or a[2].nil? then return -2,"Server error - node with id 0 found in way #{originalway}." end
- end
-
- if points.length<2 then return -2,"Server error - way is only #{points.length} points long." end
-
- # -- 3. read original way into memory
-
- xc={}; yc={}; tagc={}; vc={}
- if originalway>0
- way=originalway
- if oldversion==0 then r=readwayquery(way,false)
- else r=readwayquery_old(way,oldversion,true) end
- r.each { |row|
- id=row['id'].to_i
- if (id>0) then
- xc[id]=row['longitude'].to_f
- yc[id]=row['latitude' ].to_f
- tagc[id]=row['tags']
- vc[id]=row['visible'].to_i
- end
- }
- ActiveRecord::Base.connection.update("UPDATE current_ways SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id=#{way}")
- else
- way=ActiveRecord::Base.connection.insert("INSERT INTO current_ways (user_id,timestamp,visible) VALUES (#{uid},#{db_now},1)")