From d626256bc2f2798202dbb4656f2f53aab0815f2c Mon Sep 17 00:00:00 2001 From: Richard Fairhurst Date: Sun, 7 Oct 2007 20:26:00 +0000 Subject: [PATCH] Potlatch 0.4 (hopefully) --- app/controllers/amf_controller.rb | 497 ++++++++++-------------------- app/controllers/swf_controller.rb | 36 +-- public/potlatch/potlatch.swf | Bin 71867 -> 73599 bytes 3 files changed, 159 insertions(+), 374 deletions(-) diff --git a/app/controllers/amf_controller.rb b/app/controllers/amf_controller.rb index 8132b5311..950fd848f 100644 --- a/app/controllers/amf_controller.rb +++ b/app/controllers/amf_controller.rb @@ -13,9 +13,10 @@ class AmfController < ApplicationController # ---- talk process AMF request def talk - req=StringIO.new(request.raw_post) # Get POST data as request - req.read(2) # Skip version indicator and client ID - results={} # Results of each body + req=StringIO.new(request.raw_post+0.chr) # Get POST data as request + # (cf http://www.ruby-forum.com/topic/122163) + req.read(2) # Skip version indicator and client ID + results={} # Results of each body # ------------- # Parse request @@ -42,7 +43,6 @@ class AmfController < ApplicationController when 'getway'; results[index]=putdata(index,getway(args)) 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 @@ -94,8 +94,9 @@ motorway: highway=motorway,ref=(type road number) trunk road: highway=trunk,ref=(type road number),name=(type road name) primary road: highway=primary,ref=(type road number),name=(type road name) secondary road: highway=secondary,ref=(type road number),name=(type road name) -residential road: highway=residential,name=(type road name) -unclassified road: highway=unclassified,name=(type road name) +tertiary road: highway=tertiary,ref=,name=(type road name) +residential road: highway=residential,ref=,name=(type road name) +unclassified road: highway=unclassified,ref=,name=(type road name) way/footway footpath: highway=footway,foot=yes @@ -126,8 +127,8 @@ disused railway tracks: railway=disused course of old railway: railway=abandoned way/natural -lake: landuse=water -forest: landuse=forest +lake: natural=water,landuse= +forest: landuse=forest,natural= point/road mini roundabout: highway=mini_roundabout @@ -155,7 +156,7 @@ viaduct: railway=viaduct level crossing: railway=crossing point/natural -peak: point=peak +peak: natural=peak POI/road car park: amenity=parking @@ -221,23 +222,21 @@ EOF RAILS_DEFAULT_LOGGER.info(" Message: whichways, bbox=#{xmin},#{ymin},#{xmax},#{ymax}") - waylist = WaySegment.find_by_sql("SELECT DISTINCT current_way_segments.id AS wayid"+ - " FROM current_way_segments,current_segments,current_nodes,current_ways "+ - " WHERE segment_id=current_segments.id "+ - " AND current_segments.visible=1 "+ - " AND node_a=current_nodes.id "+ - " AND current_ways.id=current_way_segments.id "+ + waylist = ActiveRecord::Base.connection.select_all("SELECT DISTINCT current_way_nodes.id AS wayid"+ + " FROM current_way_nodes,current_nodes,current_ways "+ + " WHERE current_nodes.id=current_way_nodes.node_id "+ + " AND current_nodes.visible=1 "+ + " AND current_ways.id=current_way_nodes.id "+ " AND current_ways.visible=1 "+ " AND "+OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")) - ways = waylist.collect {|a| a.wayid.to_i } # get an array of way id's + 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.latitude*0.0000001 AS lat,current_nodes.longitude*0.0000001 AS lng,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 "+ + " LEFT OUTER JOIN current_way_nodes cwn ON cwn.node_id=current_nodes.id "+ " WHERE "+OSM.sql_for_area(ymin, xmin, ymax, xmax, "current_nodes.")+ - " AND cs1.id IS NULL AND cs2.id IS NULL "+ + " AND cwn.id IS NULL "+ " AND current_nodes.visible=1") points = pointlist.collect {|a| [a['id'],long2coord(a['lng'].to_f,baselong,masterscale),lat2coord(a['lat'].to_f,basey,masterscale),tag2array(a['tags'])] } # get a list of node ids and their tags @@ -260,20 +259,16 @@ EOF RAILS_DEFAULT_LOGGER.info(" Message: getway, id=#{wayid}") readwayquery(wayid).each {|row| - xs1=long2coord(row['long1'].to_f,baselong,masterscale); ys1=lat2coord(row['lat1'].to_f,basey,masterscale) - xs2=long2coord(row['long2'].to_f,baselong,masterscale); ys2=lat2coord(row['lat2'].to_f,basey,masterscale) - points << [xs1,ys1,row['id1'].to_i,0,tag2array(row['tags1']),0] if (row['id1'].to_i!=lastid) - lastid = row['id2'].to_i - points << [xs2,ys2,row['id2'].to_i,1,tag2array(row['tags2']),row['segment_id'].to_i] - xmin = [xmin,row['long1'].to_f,row['long2'].to_f].min - xmax = [xmax,row['long1'].to_f,row['long2'].to_f].max - ymin = [ymin,row['lat1'].to_f,row['lat2'].to_f].min - ymax = [ymax,row['lat1'].to_f,row['lat2'].to_f].max + points<<[long2coord(row['longitude'].to_f,baselong,masterscale),lat2coord(row['latitude'].to_f,basey,masterscale),row['id'].to_i,nil,tag2array(row['tags'])] + 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 } attributes={} attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM current_way_tags WHERE id=#{wayid}" - attrlist.each {|a| attributes[a['k']]=a['v'] } + attrlist.each {|a| attributes[a['k'].gsub(':','|')]=a['v'] } [objname,points,attributes,xmin,xmax,ymin,ymax] end @@ -284,10 +279,11 @@ EOF # xmin,xmax,ymin,ymax def putway(args) + RAILS_DEFAULT_LOGGER.info(" putway started") usertoken,originalway,points,attributes,baselong,basey,masterscale=args uid=getuserid(usertoken) return if !uid - db_uqs='uniq'+uid.to_s+originalway.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquesegments table name, typically 51 chars + RAILS_DEFAULT_LOGGER.info(" putway authenticated happily") db_uqn='unin'+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'+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()") @@ -297,13 +293,14 @@ EOF # -- 3. read original way into memory - xc={}; yc={}; tagc={}; seg={} + xc={}; yc={}; tagc={} if originalway>0 way=originalway readwayquery(way).each { |row| - id1=row['id1'].to_i; xc[id1]=row['long1'].to_f; yc[id1]=row['lat1'].to_f; tagc[id1]=row['tags1'] - id2=row['id2'].to_i; xc[id2]=row['long2'].to_f; yc[id2]=row['lat2'].to_f; tagc[id2]=row['tags2'] - seg[row['segment_id'].to_i]=id1.to_s+'-'+id2.to_s + id=row['id'].to_i + xc[id]=row['longitude'].to_f + yc[id]=row['latitude' ].to_f + tagc[id]=row['tags'] } ActiveRecord::Base.connection.update("UPDATE current_ways SET timestamp=#{db_now},user_id=#{uid},visible=1 WHERE id=#{way}") else @@ -316,10 +313,11 @@ EOF # -- 5. compare nodes and update xmin,xmax,ymin,ymax - xmin = ymin = 999999 - xmax = ymax = -999999 - insertsql = '' + xmin=ymin= 999999 + xmax=ymax=-999999 + insertsql='' renumberednodes={} + nodelist=[] points.each_index do |i| xs=coord2long(points[i][0],masterscale,baselong) @@ -327,8 +325,7 @@ EOF xmin=[xs,xmin].min; xmax=[xs,xmax].max ymin=[ys,ymin].min; ymax=[ys,ymax].max node=points[i][2].to_i - tagstr=array2tag(points[i][4]) - tagstr=tagstr.gsub(/[\000-\037]/,"") + tagstr=array2tag(points[i][4]) tagsql="'"+sqlescape(tagstr)+"'" lat=(ys * 10000000).round long=(xs * 10000000).round @@ -337,18 +334,20 @@ EOF # compare node if node<0 # new node - create - if renumberednodes[node.to_s].nil? + if renumberednodes[node.to_s].nil? newnode=ActiveRecord::Base.connection.insert("INSERT INTO current_nodes ( latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES ( #{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{newnode},#{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") points[i][2]=newnode + nodelist.push(newnode) renumberednodes[node.to_s]=newnode.to_s - else + else points[i][2]=renumberednodes[node.to_s].to_i - end + end elsif xc.has_key?(node) + nodelist.push(node) # old node from original way - update - if (xs!=xc[node] or ys!=yc[node] or tagstr!=tagc[node]) + if (xs!=xc[node] or (ys/0.0000001).round!=(yc[node]/0.0000001).round or tagstr!=tagc[node]) ActiveRecord::Base.connection.insert("INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tags,tile) VALUES (#{node},#{lat},#{long},#{db_now},#{uid},1,#{tagsql},#{tile})") ActiveRecord::Base.connection.update("UPDATE current_nodes SET latitude=#{lat},longitude=#{long},timestamp=#{db_now},user_id=#{uid},tags=#{tagsql},visible=1,tile=#{tile} WHERE id=#{node}") end @@ -358,58 +357,9 @@ EOF end - # -- 6.i compare segments - - numberedsegments={} - seglist='' # list of existing segments that we want to keep - for i in (0..(points.length-2)) - if (points[i+1][3].to_i==0) then next end - segid=points[i+1][5].to_i - from =points[i ][2].to_i - to =points[i+1][2].to_i - if seg.has_key?(segid) - # if segment exists, check it still refers to the same nodes - if seg[segid]=="#{from}-#{to}" then - if (seglist!='') then seglist+=',' end; seglist+=segid.to_s - next - end - elsif segid>0 - # not in previous version of way, but supplied, so assume - # that it's come from makeway (i.e. unwayed segments) - if (seglist!='') then seglist+=',' end; seglist+=segid.to_s - next - end - segid=ActiveRecord::Base.connection.insert("INSERT INTO current_segments ( node_a,node_b,timestamp,user_id,visible,tags) VALUES ( #{from},#{to},#{db_now},#{uid},1,'')") - ActiveRecord::Base.connection.insert("INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible,tags) VALUES (#{segid},#{from},#{to},#{db_now},#{uid},1,'')") - points[i+1][5]=segid - numberedsegments[(i+1).to_s]=segid.to_s - end - - - # -- 6.ii insert new way segments - - createuniquesegments(way,db_uqs,seglist) # segments which appear in this way but no other - - # delete segments from uniquesegments (and not in modified way) - - sql=<<-EOF - INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible) - SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0 - FROM current_segments AS cs, #{db_uqs} AS us - WHERE cs.id=us.segment_id AND cs.visible=1 - EOF - ActiveRecord::Base.connection.insert(sql) - - sql=<<-EOF - UPDATE current_segments AS cs, #{db_uqs} AS us - SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} - WHERE cs.id=us.segment_id AND cs.visible=1 - EOF - ActiveRecord::Base.connection.update(sql) - - # delete nodes not in modified way or any other segments + # -- 6a. delete any nodes not in modified way - createuniquenodes(db_uqs,db_uqn) # nodes which appear in this way but no other + createuniquenodes(way,db_uqn,nodelist) # nodes which appear in this way but no other sql=<<-EOF INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tile) @@ -426,26 +376,25 @@ EOF EOF ActiveRecord::Base.connection.update(sql) - ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqs}") + deleteuniquenoderelations(db_uqn,uid,db_now) ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqn}") - # insert new version of route into way_segments + # 6b. insert new version of route into way_nodes insertsql ='' currentsql='' sequence =1 - for i in (0..(points.length-2)) - if (points[i+1][3].to_i==0) then next end + points.each do |p| if insertsql !='' then insertsql +=',' end if currentsql!='' then currentsql+=',' end - insertsql +="(#{way},#{points[i+1][5]},#{version})" - currentsql+="(#{way},#{points[i+1][5]},#{sequence})" + insertsql +="(#{way},#{p[2]},#{sequence},#{version})" + currentsql+="(#{way},#{p[2]},#{sequence})" sequence +=1 end - ActiveRecord::Base.connection.execute("DELETE FROM current_way_segments WHERE id=#{way}"); - ActiveRecord::Base.connection.insert("INSERT INTO way_segments (id,segment_id,version ) VALUES #{insertsql}"); - ActiveRecord::Base.connection.insert("INSERT INTO current_way_segments (id,segment_id,sequence_id) VALUES #{currentsql}"); + ActiveRecord::Base.connection.execute("DELETE FROM current_way_nodes WHERE id=#{way}"); + ActiveRecord::Base.connection.insert( "INSERT INTO way_nodes (id,node_id,sequence_id,version) VALUES #{insertsql}"); + ActiveRecord::Base.connection.insert( "INSERT INTO current_way_nodes (id,node_id,sequence_id ) VALUES #{currentsql}"); # -- 7. insert new way tags @@ -456,17 +405,15 @@ EOF if v[0,6]=='(type ' then next end if insertsql !='' then insertsql +=',' end if currentsql!='' then currentsql+=',' end - k=k.gsub(/[\000-\037]/,"") - v=v.gsub(/[\000-\037]/,"") - insertsql +="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"',#{version})" - currentsql+="(#{way},'"+sqlescape(k)+"','"+sqlescape(v)+"')" + insertsql +="(#{way},'"+sqlescape(k.gsub('|',':'))+"','"+sqlescape(v)+"',#{version})" + currentsql+="(#{way},'"+sqlescape(k.gsub('|',':'))+"','"+sqlescape(v)+"')" end ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}") if (insertsql !='') then ActiveRecord::Base.connection.insert("INSERT INTO way_tags (id,k,v,version) VALUES #{insertsql}" ) end if (currentsql!='') then ActiveRecord::Base.connection.insert("INSERT INTO current_way_tags (id,k,v) VALUES #{currentsql}") end - [originalway,way,renumberednodes,numberedsegments,xmin,xmax,ymin,ymax] + [originalway,way,renumberednodes,xmin,xmax,ymin,ymax] end # ----- putpoi (user token, id, x,y,tag array,visible,baselong,basey,masterscale) @@ -483,6 +430,13 @@ EOF id=id.to_i visible=visible.to_i + if visible==0 then + # if deleting, check node hasn't become part of a way + inway=ActiveRecord::Base.connection.select_one("SELECT cw.id FROM current_ways cw,current_way_nodes cwn WHERE cw.id=cwn.id AND cw.visible=1 AND cwn.node_id=#{id} LIMIT 1") + unless inway.nil? then return [id,id] end # should really return an error + deleteitemrelations(id,'node',uid,db_now) + end + x=coord2long(x.to_f,masterscale,baselong) y=coord2lat(y.to_f,masterscale,basey) tagsql="'"+sqlescape(array2tag(tags))+"'" @@ -515,43 +469,28 @@ EOF tag2array(poi['tags'])] end - # ----- deleteway (user token, way) + # ----- deleteway (user token, way, nodes to keep) # returns way ID only def deleteway(args) - usertoken,way=args + usertoken,way,preserve=args RAILS_DEFAULT_LOGGER.info(" Message: deleteway, id=#{way}") uid=getuserid(usertoken); if !uid then return end way=way.to_i - db_uqs='uniq'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquesegments table name, typically 51 chars db_uqn='unin'+uid.to_s+way.to_i.abs.to_s+Time.new.to_i.to_s # temp uniquenodes table name, typically 51 chars db_now='@now'+uid.to_s+way.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()") - createuniquesegments(way,db_uqs,'') - - # - delete any otherwise unused segments - - sql=<<-EOF - INSERT INTO segments (id,node_a,node_b,timestamp,user_id,visible) - SELECT DISTINCT segment_id,node_a,node_b,#{db_now},#{uid},0 - FROM current_segments AS cs, #{db_uqs} AS us - WHERE cs.id=us.segment_id - EOF - ActiveRecord::Base.connection.insert(sql) - - sql=<<-EOF - UPDATE current_segments AS cs, #{db_uqs} AS us - SET cs.timestamp=#{db_now},cs.visible=0,cs.user_id=#{uid} - WHERE cs.id=us.segment_id - EOF - ActiveRecord::Base.connection.update(sql) - # - delete any unused nodes + # - delete any otherwise unused nodes - createuniquenodes(db_uqs,db_uqn) + createuniquenodes(way,db_uqn,[]) + + unless (preserve.empty?) then + ActiveRecord::Base.connection.execute("DELETE FROM #{db_uqn} WHERE node_id IN ("+preserve.join(',')+")") + end sql=<<-EOF INSERT INTO nodes (id,latitude,longitude,timestamp,user_id,visible,tile) @@ -567,234 +506,114 @@ EOF WHERE cn.id=node_id EOF ActiveRecord::Base.connection.update(sql) - - ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqs}") + + deleteuniquenoderelations(db_uqn,uid,db_now) ActiveRecord::Base.connection.execute("DROP TABLE #{db_uqn}") # - delete way ActiveRecord::Base.connection.insert("INSERT INTO ways (id,user_id,timestamp,visible) VALUES (#{way},#{uid},#{db_now},0)") ActiveRecord::Base.connection.update("UPDATE current_ways SET user_id=#{uid},timestamp=#{db_now},visible=0 WHERE id=#{way}") - ActiveRecord::Base.connection.execute("DELETE FROM current_way_segments WHERE id=#{way}") + ActiveRecord::Base.connection.execute("DELETE FROM current_way_nodes WHERE id=#{way}") ActiveRecord::Base.connection.execute("DELETE FROM current_way_tags WHERE id=#{way}") - + deleteitemrelations(way,'way',uid,db_now) way end -# ----- makeway(x,y,baselong,basey,masterscale) -# returns way made from unwayed segments - -def makeway(args) - usertoken,x,y,baselong,basey,masterscale=args - uid=getuserid(usertoken) - return if !uid - - points=[] - toreverse=[] # segments to reverse - nodesused={} # so we don't go over the same node twice - - # - find start point near x - - xc=coord2long(x,masterscale,baselong) - yc=coord2lat(y,masterscale,basey) - RAILS_DEFAULT_LOGGER.info(" Message: makeway, xc=#{xc}, y=#{yc}") - xs1=xc-0.001; xs2=xc+0.001 - ys1=yc-0.001; ys2=yc+0.001 - - sql=<<-EOF - SELECT cn1.latitude*0.0000001 AS lat1,cn1.longitude*0.0000001 AS lon1,cn1.id AS id1, - cn2.latitude*0.0000001 AS lat2,cn2.longitude*0.0000001 AS lon2,cn2.id AS id2, cs.id AS segid - FROM current_nodes AS cn1, - current_nodes AS cn2, - current_segments AS cs - LEFT OUTER JOIN current_way_segments ON segment_id=cs.id - WHERE #{OSM.sql_for_area(ys1,xs1,ys2,xs2,"cn1.")} - AND segment_id IS NULL - AND cs.visible=1 - AND cn1.id=node_a AND cn1.visible=1 - AND cn2.id=node_b AND cn2.visible=1 - ORDER BY SQRT(POW(cn1.longitude-#{xc},2)+ - POW(cn1.latitude -#{yc},2)) - LIMIT 1 - EOF - row=ActiveRecord::Base.connection.select_one sql - if row.nil? then return [0,0,0,0,0] end - xs1=long2coord(row['lon1'].to_f,baselong,masterscale); ys1=lat2coord(row['lat1'].to_f,basey,masterscale) - xs2=long2coord(row['lon2'].to_f,baselong,masterscale); ys2=lat2coord(row['lat2'].to_f,basey,masterscale) - xmin=[xs1,xs2].min; xmax=[xs1,xs2].max - ymin=[ys1,ys2].min; ymax=[ys1,ys2].max - nodesused[row['id1'].to_i]=true - nodesused[row['id2'].to_i]=true - points<<[xs1,ys1,row['id1'].to_i,1,{},0] - points<<[xs2,ys2,row['id2'].to_i,1,{},row['segid'].to_i] - - # - extend at start, then end - while (a,point,nodesused,toreverse=findconnect(points[0][2],nodesused,'b',toreverse,baselong,basey,masterscale))[0] - points[0][5]=point[5]; point[5]=0 # segment leads to next node - points.unshift(point) - xmin=[point[0],xmin].min; xmax=[point[0],xmax].max - ymin=[point[1],ymin].min; ymax=[point[1],ymax].max - end - while (a,point,nodesused,toreverse=findconnect(points[-1][2],nodesused,'a',toreverse,baselong,basey,masterscale))[0] - points.push(point) - xmin=[point[0],xmin].min; xmax=[point[0],xmax].max - ymin=[point[1],ymin].min; ymax=[point[1],ymax].max - end - points[0][3]=0 # start with a move - - # reverse segments in toreverse - if toreverse.length>0 - sql=<<-EOF - UPDATE current_segments c1, current_segments c2 - SET c1.node_a=c2.node_b,c1.node_b=c2.node_a, - c1.timestamp=NOW(),c1.user_id=#{uid} - WHERE c1.id=c2.id - AND c1.id IN (#{toreverse.join(',')}) - EOF - ActiveRecord::Base.connection.update sql - sql=<<-EOF - INSERT INTO segments - (SELECT * FROM current_segments - WHERE id IN (#{toreverse.join(',')})) - EOF - ActiveRecord::Base.connection.insert sql - end +# ==================================================================== +# Support functions for remote calls - [points,xmin,xmax,ymin,ymax] +def readwayquery(id) + ActiveRecord::Base.connection.select_all "SELECT latitude*0.0000001 AS latitude,longitude*0.0000001 AS longitude,current_nodes.id,tags "+ + " FROM current_way_nodes,current_nodes "+ + " WHERE current_way_nodes.id=#{id} "+ + " AND current_way_nodes.node_id=current_nodes.id "+ + " AND current_nodes.visible=1 "+ + " ORDER BY sequence_id" end -def findconnect(id,nodesused,lookfor,toreverse,baselong,basey,masterscale) - # get all segments with 'id' as a point - # (to look for both node_a and node_b, UNION is faster than node_a=id OR node_b=id)! +def createuniquenodes(way,uqn_name,nodelist) + # Find nodes which appear in this way but no others sql=<<-EOF - SELECT cn1.latitude*0.0000001 AS lat1,cn1.longitude*0.0000001 AS lon1,cn1.id AS id1, - cn2.latitude*0.0000001 AS lat2,cn2.longitude*0.0000001 AS lon2,cn2.id AS id2, cs.id AS segid - FROM current_nodes AS cn1, - current_nodes AS cn2, - current_segments AS cs - LEFT OUTER JOIN current_way_segments ON segment_id=cs.id - WHERE segment_id IS NULL - AND cs.visible=1 - AND cn1.id=node_a AND cn1.visible=1 - AND cn2.id=node_b AND cn2.visible=1 - AND node_a=#{id} - UNION - SELECT cn1.latitude*0.0000001 AS lat1,cn1.longitude*0.0000001 AS lon1,cn1.id AS id1, - cn2.latitude*0.0000001 AS lat2,cn2.longitude*0.0000001 AS lon2,cn2.id AS id2, cs.id AS segid - FROM current_nodes AS cn1, - current_nodes AS cn2, - current_segments AS cs - LEFT OUTER JOIN current_way_segments ON segment_id=cs.id - WHERE segment_id IS NULL - AND cs.visible=1 - AND cn1.id=node_a AND cn1.visible=1 - AND cn2.id=node_b AND cn2.visible=1 - AND node_b=#{id} + CREATE TEMPORARY TABLE #{uqn_name} + SELECT a.node_id + FROM (SELECT DISTINCT node_id FROM current_way_nodes + WHERE id=#{way}) a + LEFT JOIN current_way_nodes b + ON b.node_id=a.node_id + AND b.id!=#{way} + WHERE b.node_id IS NULL EOF - connectlist=ActiveRecord::Base.connection.select_all sql - - if lookfor=='b' then tocol='id1'; tolat='lat1'; tolon='lon1'; fromcol='id2'; fromlat='lat2'; fromlon='lon2' - else tocol='id2'; tolat='lat2'; tolon='lon2'; fromcol='id1'; fromlat='lat1'; fromlon='lon1' - end - - # eliminate those already in the hash - connex=0 - point=nil - connectlist.each { |row| - tonode=row[tocol].to_i - fromnode=row[fromcol].to_i - if id==tonode and !nodesused.has_key?(fromnode) - # wrong way round; add, then add to 'segments to reverse' list - connex+=1 - nodesused[fromnode]=true - point=[long2coord(row[fromlon].to_f,baselong,masterscale),lat2coord(row[fromlat].to_f,basey,masterscale),fromnode,1,{},row['segid'].to_i] - toreverse.push(row['segid'].to_i) - elsif id==fromnode and !nodesused.has_key?(tonode) - # right way round; just add - connex+=1 - point=[long2coord(row[tolon].to_f,baselong,masterscale),lat2coord(row[tolat].to_f,basey,masterscale),tonode,1,{},row['segid'].to_i] - nodesused[tonode]=true - end - } - - # if only one left, then add it; otherwise return false - if connex!=1 or point.nil? then - return [false,[],nodesused,toreverse] - else - return [true,point,nodesused,toreverse] + unless nodelist.empty? then + sql+="AND a.node_id NOT IN ("+nodelist.join(',')+")" end + ActiveRecord::Base.connection.execute(sql) end + # ==================================================================== -# Support functions for remote calls +# Relations handling +# deleteuniquenoderelations(uqn_name,uid,db_now) +# deleteitemrelations(way|node,'way'|'node',uid,db_now) -def readwayquery(id) - ActiveRecord::Base.connection.select_all "SELECT n1.latitude*0.0000001 AS lat1,n1.longitude*0.0000001 AS long1,n1.id AS id1,n1.tags as tags1, "+ - " n2.latitude*0.0000001 AS lat2,n2.longitude*0.0000001 AS long2,n2.id AS id2,n2.tags as tags2,segment_id "+ - " FROM current_way_segments,current_segments,current_nodes AS n1,current_nodes AS n2 "+ - " WHERE current_way_segments.id=#{id} "+ - " AND segment_id=current_segments.id "+ - " AND current_segments.visible=1 "+ - " AND n1.id=node_a AND n2.id=node_b "+ - " AND n1.visible=1 AND n2.visible=1 "+ - " ORDER BY sequence_id" -end +def deleteuniquenoderelations(uqn_name,uid,db_now) + sql=<<-EOF + SELECT node_id,cr.id FROM #{uqn_name},current_relation_members crm,current_relations cr + WHERE crm.member_id=node_id + AND crm.member_type='node' + AND crm.id=cr.id + AND cr.visible=1 + EOF -def createuniquesegments(way,uqs_name,seglist) - # Finds segments which appear in (previous version of) this way and no other - sql=<<-EOF - CREATE TEMPORARY TABLE #{uqs_name} - SELECT a.segment_id - FROM (SELECT DISTINCT segment_id FROM current_way_segments - WHERE id = #{way}) a - LEFT JOIN current_way_segments b - ON b.segment_id = a.segment_id - AND b.id != #{way} - WHERE b.segment_id IS NULL - EOF - if (seglist!='') then sql+=" AND a.segment_id NOT IN (#{seglist})" end - ActiveRecord::Base.connection.execute(sql) + relnodes=ActiveRecord::Base.connection.select_all(sql) + relnodes.each do |a| + removefromrelation(a['node_id'],'node',a['id'],uid,db_now) + end end -def createuniquenodes(uqs_name,uqn_name) - # Finds nodes which appear in uniquesegments but no other segments +def deleteitemrelations(objid,type,uid,db_now) 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) 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 + SELECT cr.id FROM current_relation_members crm,current_relations cr + WHERE crm.member_id=#{objid} + AND crm.member_type='#{type}' + AND crm.id=cr.id + AND cr.visible=1 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 + + relways=ActiveRecord::Base.connection.select_all(sql) + relways.each do |a| + removefromrelation(objid,type,a['id'],uid,db_now) + end +end + +def removefromrelation(objid,type,relation,uid,db_now) + rver=ActiveRecord::Base.connection.insert("INSERT INTO relations (id,user_id,timestamp,visible) VALUES (#{relation},#{uid},#{db_now},1)") + + tagsql=<<-EOF + INSERT INTO relation_tags (id,k,v,version) + SELECT id,k,v,#{rver} FROM current_relation_tags + WHERE id=#{relation} EOF - ActiveRecord::Base.connection.execute(sql) + ActiveRecord::Base.connection.insert(tagsql) + + membersql=<<-EOF + INSERT INTO relation_members (id,member_type,member_id,member_role,version) + SELECT id,member_type,member_id,member_role,#{rver} FROM current_relation_members + WHERE id=#{relation} + AND (member_id!=#{objid} OR member_type!='#{type}') + EOF + ActiveRecord::Base.connection.insert(membersql) + + ActiveRecord::Base.connection.update("UPDATE current_relations SET user_id=#{uid},timestamp=#{db_now} WHERE id=#{relation}") + ActiveRecord::Base.connection.execute("DELETE FROM current_relation_members WHERE id=#{relation} AND member_type='#{type}' AND member_id=#{objid}") end + def sqlescape(a) - a.gsub("'","''").gsub(92.chr,92.chr+92.chr) + a.gsub(/[\000-\037]/,"").gsub("'","''").gsub(92.chr,92.chr+92.chr) end def tag2array(a) @@ -805,7 +624,7 @@ def tag2array(a) k,v=b.split('=') if k.nil? then k='' end if v.nil? then v='' end - tags[k.gsub('#%','=')]=v.gsub('#%','=') + tags[k.gsub('#%','=').gsub(':','|')]=v.gsub('#%','=') end tags end @@ -816,7 +635,7 @@ def array2tag(a) if v=='' then next end if v[0,6]=='(type ' then next end if str!='' then str+=';' end - str+=k.gsub(';',';;;').gsub('=','===')+'='+v.gsub(';',';;;').gsub('=','===') + str+=k.gsub(';',';;;').gsub('=','===').gsub('|',':')+'='+v.gsub(';',';;;').gsub('=','===') end str end @@ -884,16 +703,16 @@ end def getvalue(s) case s.getc - when 0; return getdouble(s) # number - when 1; return s.getc # boolean - when 2; return getstring(s) # string - when 3; return getobject(s) # object/hash - when 5; return nil # null - when 6; return nil # undefined - when 8; s.read(4) # mixedArray - return getobject(s) # | - when 10; return getarray(s) # array - else; return nil # error + when 0; return getdouble(s) # number + when 1; return s.getc # boolean + when 2; return getstring(s) # string + when 3; return getobject(s) # object/hash + when 5; return nil # null + when 6; return nil # undefined + when 8; s.read(4) # mixedArray + return getobject(s) # | + when 10;return getarray(s) # array + else; return nil # error end end diff --git a/app/controllers/swf_controller.rb b/app/controllers/swf_controller.rb index 40969c20f..2c9d64548 100644 --- a/app/controllers/swf_controller.rb +++ b/app/controllers/swf_controller.rb @@ -86,41 +86,7 @@ class SwfController < ApplicationController end end - # - Draw unwayed segments - - if params['unwayed']=='true' - sql="SELECT cn1.latitude*0.0000001 AS lat1,cn1.longitude*0.0000001 AS lon1,"+ - " cn2.latitude*0.0000001 AS lat2,cn2.longitude*0.0000001 AS lon2 "+ - " FROM current_segments "+ - " LEFT OUTER JOIN current_way_nodes"+ - " ON segment_id=current_segments.id,"+ - " current_nodes AS cn1,current_nodes AS cn2"+ - " WHERE "+OSM.sql_for_area(ymin,xmin,ymax,xmax,"cn1.")+ - " AND segment_id IS NULL"+ - " AND current_segments.visible=1"+ - " AND cn1.id=node_a AND cn1.visible=1"+ - " AND cn2.id=node_b AND cn2.visible=1" - seglist=ActiveRecord::Base.connection.select_all sql - - seglist.each do |row| - xs1=(long2coord(row['lon1'].to_f,baselong,masterscale)*20).floor; ys1=(lat2coord(row['lat1'].to_f,basey,masterscale)*20).floor - xs2=(long2coord(row['lon2'].to_f,baselong,masterscale)*20).floor; ys2=(lat2coord(row['lat2'].to_f,basey,masterscale)*20).floor - if (xs1==absx and ys1==absy) - b+=drawTo(absx,absy,xs2,ys2) - absx=xs2; absy=ys2 - elsif (xs2==absx and ys2==absy) - b+=drawTo(absx,absy,xs1,ys1) - absx=xs1; absy=ys1 - else - b+=startAndMove(xs1,ys1,'10') - b+=drawTo(xs1,ys1,xs2,ys2) - absx=xs2; absy=ys2 - end - while b.length>80 do - r+=[b.slice!(0...80)].pack("B*") - end - end - end + # (Unwayed segments removed) # - Write shape diff --git a/public/potlatch/potlatch.swf b/public/potlatch/potlatch.swf index ce4cd00a4dd16a69b690450eb864d5fde394efed..808699532e886410721656e23fb218da42b2c425 100755 GIT binary patch literal 73599 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