1 class AmfController < ApplicationController
6 # - user authentication
7 # - (also pass lat/lon through from view tab to edit tab)
10 # RAILS_DEFAULT_LOGGER.error("Args: #{args[0]}, #{args[1]}, #{args[2]}, #{args[3]}")
13 # ====================================================================
16 # ---- talk process AMF request
19 req=StringIO.new(request.raw_post) # Get POST data as request
20 req.read(2) # Skip version indicator and client ID
21 results={} # Results of each body
26 headers=getint(req) # Read number of headers
27 for i in (1..headers) # Read each header
28 name=getstring(req) # |
29 req.getc # | skip boolean
30 value=getvalue(req) # |
31 header["name"]=value # |
34 bodies=getint(req) # Read number of bodies
35 for i in (1..bodies) # Read each body
36 message=getstring(req) # | get message name
37 index=getstring(req) # | get index in response sequence
38 bytes=getlong(req) # | get total size in bytes
39 args=getvalue(req) # | get response (probably an array)
42 when 'getpresets'; results[index]=putdata(index,getpresets)
43 when 'whichways'; results[index]=putdata(index,whichways(args))
44 when 'getway'; results[index]=putdata(index,getway(args))
45 when 'putway'; results[index]=putdata(index,putway(args))
46 when 'deleteway'; results[index]=putdata(index,deleteway(args))
53 response.headers["Content-Type"]="application/x-amf"
54 a,b=results.length.divmod(256)
55 ans=0.chr+0.chr+0.chr+0.chr+a.chr+b.chr
64 # ====================================================================
69 presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]
70 presetnames={}; presetnames['point']={}; presetnames['way']={}
74 File.open("config/potlatch/presets.txt") do |file|
75 file.each_line {|line|
77 if (t=~/(\w+)\/(\w+)/) then
80 presetmenus[presettype].push(presetcategory)
81 presetnames[presettype][presetcategory]=["(no preset)"]
82 elsif (t=~/^(.+):\s?(.+)$/) then
84 presetnames[presettype][presetcategory].push(pre)
86 kv.split(',').each {|a|
87 if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end
92 [presets,presetmenus,presetnames]
96 waylist=WaySegment.find_by_sql("SELECT DISTINCT current_way_segments.id AS wayid"+
97 " FROM current_way_segments,current_segments,current_nodes "+
98 " WHERE segment_id=current_segments.id "+
99 " AND node_a=current_nodes.id "+
100 " AND (latitude BETWEEN "+(args[1].to_f-0.01).to_s+" AND "+(args[3].to_f+0.01).to_s+") "+
101 " AND (longitude BETWEEN "+(args[0].to_f-0.01).to_s+" AND "+(args[2].to_f+0.01).to_s+")")
105 RAILS_DEFAULT_LOGGER.error("Found #{a.wayid.to_i}")
111 objname,wayid,$baselong,$basey,$masterscale=args
115 xmin=999999; xmax=-999999
116 ymin=999999; ymax=-999999
118 RAILS_DEFAULT_LOGGER.error("Looking for way #{wayid}")
119 nodelist=ActiveRecord::Base.connection.select_all "SELECT n1.latitude AS lat1,n1.longitude AS long1,n1.id AS id1,n1.tags as tags1, "+
120 " n2.latitude AS lat2,n2.longitude AS long2,n2.id AS id2,n2.tags as tags2,segment_id "+
121 " FROM current_way_segments,current_segments,current_nodes AS n1,current_nodes AS n2 "+
122 " WHERE current_way_segments.id=#{wayid} "+
123 " AND segment_id=current_segments.id "+
124 " AND n1.id=node_a and n2.id=node_b "+
125 " ORDER BY sequence_id"
127 xs1=long2coord(row['long1'].to_f); ys1=lat2coord(row['lat1'].to_f)
128 xs2=long2coord(row['long2'].to_f); ys2=lat2coord(row['lat2'].to_f)
129 if (row['id1'].to_i!=lastid)
130 points<<[xs1,ys1,row['id1'].to_i,0,tag2array(row['tags1']),0]
132 lastid=row['id2'].to_i
133 points<<[xs2,ys2,row['id2'].to_i,1,tag2array(row['tags2']),row['segment_id'].to_i]
134 xmin=[xmin,row['long1'].to_f,row['long2'].to_f].min
135 xmax=[xmax,row['long1'].to_f,row['long2'].to_f].max
136 ymin=[ymin,row['lat1'].to_f,row['lat2'].to_f].min
137 ymax=[ymax,row['lat1'].to_f,row['lat2'].to_f].max
141 attrlist=ActiveRecord::Base.connection.select_all "SELECT k,v FROM current_way_tags WHERE id=#{wayid}"
142 attrlist.each {|a| attributes[a['k']]=a['v'] }
144 RAILS_DEFAULT_LOGGER.error("Way #{wayid} #{xmin},#{xmax},#{ymin},#{ymax}")
145 [objname,points,attributes,xmin,xmax,ymin,ymax]
156 # need support functions here too:
157 # database support functions (readwayquery, createuniquesegments)
158 # tag2array, array2tag
163 a.gsub('\;','#%').split(';').each do |b|
172 # ====================================================================
173 # AMF read subroutines
175 # ----- getint return two-byte integer
176 # ----- getlong return four-byte long
177 # ----- getstring return string with two-byte length
178 # ----- getdouble return eight-byte double-precision float
179 # ----- getobject return object/hash
180 # ----- getarray return numeric array
187 ((s.getc*256+s.getc)*256+s.getc)*256+s.getc
191 len=s.getc*256+s.getc
196 a=s.read(8).unpack('G') # G big-endian, E little-endian
211 while (key=getstring(s))
212 if (key=='') then break end
215 s.getc # skip the 9 'end of object' value
219 # ----- getvalue parse and get value
223 when 0; return getdouble(s) # number
224 when 1; return s.getc # boolean
225 when 2; return getstring(s) # string
226 when 3; return getobject(s) # object/hash
227 when 5; return nil # null
228 when 6; return nil # undefined
229 when 8; s.read(4) # mixedArray
230 return getobject(s) # |
231 when 10;return getarray(s) # array
232 else; return nil # error
236 # ====================================================================
237 # AMF write subroutines
239 # ----- putdata envelope data into AMF writeable form
240 # ----- encodevalue pack variables as AMF
243 d =encodestring(index+"/onResult")
244 d+=encodestring("null")
252 a=10.chr+encodelong(n.length)
260 a+=encodestring(k)+encodevalue(v)
264 2.chr+encodestring(n)
265 when 'Bignum','Fixnum','Float'
266 0.chr+encodedouble(n)
270 RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
274 # ----- encodestring encode string with two-byte length
275 # ----- encodedouble encode number as eight-byte double precision float
276 # ----- encodelong encode number as four-byte long
279 a,b=n.size.divmod(256)
291 # ====================================================================
292 # Co-ordinate conversion
295 -(lat2y(a)-$basey)*$masterscale+250
299 (a-$baselong)*$masterscale+350
303 180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2))
307 y2lat((a-250)/-$masterscale+$basey)
311 (a-350)/$masterscale+$baselong
315 180/Math::PI * (2*Math.atan(Math.exp(a*Math::PI/180))-Math::PI/2)