- 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_segments 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_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 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_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}
- 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
-