X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/285d61bf4cd6cd93e6ae0f4905db9faf4a6f71f5..33a65a90c9d0e2ab121e1da9c3efedaf9e6a9789:/lib/quad_tile.rb diff --git a/lib/quad_tile.rb b/lib/quad_tile.rb new file mode 100644 index 000000000..cb1b5a06e --- /dev/null +++ b/lib/quad_tile.rb @@ -0,0 +1,81 @@ +module QuadTile + begin + require "quad_tile/quad_tile_so" + rescue MissingSourceFile + def self.tile_for_point(lat, lon) + x = ((lon + 180) * 65535 / 360).round + y = ((lat + 90) * 65535 / 180).round + + return tile_for_xy(x, y) + end + + def self.tiles_for_area(minlat, minlon, maxlat, maxlon) + minx = ((minlon + 180) * 65535 / 360).round + maxx = ((maxlon + 180) * 65535 / 360).round + miny = ((minlat + 90) * 65535 / 180).round + maxy = ((maxlat + 90) * 65535 / 180).round + tiles = [] + + minx.upto(maxx) do |x| + miny.upto(maxy) do |y| + tiles << tile_for_xy(x, y) + end + end + + return tiles + end + + def self.tile_for_xy(x, y) + t = 0 + + 16.times do + t = t << 1 + t = t | 1 unless (x & 0x8000).zero? + x <<= 1 + t = t << 1 + t = t | 1 unless (y & 0x8000).zero? + y <<= 1 + end + + return t + end + end + + def self.sql_for_area(minlat, minlon, maxlat, maxlon) + sql = Array.new + single = Array.new + + iterate_tiles_for_area(minlat, minlon, maxlat, maxlon) do |first,last| + if first == last + single.push(first) + else + sql.push("tile BETWEEN #{first} AND #{last}") + end + end + + sql.push("tile IN (#{single.join(',')})") if single.size > 0 + + return "( " + sql.join(" OR ") + " )" + end + + def self.iterate_tiles_for_area(minlat, minlon, maxlat, maxlon) + tiles = tiles_for_area(minlat, minlon, maxlat, maxlon) + first = last = nil + + tiles.sort.each do |tile| + if last.nil? + first = last = tile + elsif tile == last + 1 + last = tile + else + yield first, last + + first = last = tile + end + end + + yield first, last unless last.nil? + end + + private_class_method :tile_for_xy, :iterate_tiles_for_area +end