- 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 AS lat1,cn1.longitude AS lon1,cn1.id AS id1,
- cn2.latitude AS lat2,cn2.longitude 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_nodes ON segment_id=cs.id
- WHERE (cn1.longitude BETWEEN #{xs1} AND #{xs2})
- AND (cn1.latitude BETWEEN #{ys1} AND #{ys2})
- 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
-
- [points,xmin,xmax,ymin,ymax]
-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)!
- sql=<<-EOF
- SELECT cn1.latitude AS lat1,cn1.longitude AS lon1,cn1.id AS id1,
- cn2.latitude AS lat2,cn2.longitude 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_nodes 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 AS lat1,cn1.longitude AS lon1,cn1.id AS id1,
- cn2.latitude AS lat2,cn2.longitude 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_nodes 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}
- 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]
- end
-end
-
-
-# ====================================================================
-# Support functions for remote calls
-
-def readwayquery(id)
- ActiveRecord::Base.connection.select_all "SELECT n1.latitude AS lat1,n1.longitude AS long1,n1.id AS id1,n1.tags as tags1, "+
- " n2.latitude AS lat2,n2.longitude AS long2,n2.id AS id2,n2.tags as tags2,segment_id "+
- " FROM current_way_nodes,current_segments,current_nodes AS n1,current_nodes AS n2 "+
- " WHERE current_way_nodes.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 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_nodes
- WHERE id = #{way}) a
- LEFT JOIN current_way_nodes 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)
-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) 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
-
-def sqlescape(a)
- a.gsub("'","''").gsub(92.chr,92.chr+92.chr)
-end
-
-def tag2array(a)
- tags={}
- a.gsub(';;;','#%').split(';').each do |b|
- b.gsub!('#%',';;;')
- b.gsub!('===','#%')
- k,v=b.split('=')
- if k.nil? then k='' end
- if v.nil? then v='' end
- tags[k.gsub('#%','=')]=v.gsub('#%','=')