Remove quad_tile library and extract to gem
Quad tile functions are now installed via a gem with native extension automatically. This improves the run time of the test suite by ~30% for users that didn't bother to build the C version of the functions. Closes #1314 Closes #1899
This commit is contained in:
parent
39a1600c3a
commit
d5672aed4a
10 changed files with 6 additions and 292 deletions
|
@ -1,81 +0,0 @@
|
|||
module QuadTile
|
||||
begin
|
||||
require "quad_tile/quad_tile_so"
|
||||
rescue LoadError
|
||||
def self.tile_for_point(lat, lon)
|
||||
x = ((lon.to_f + 180) * 65535 / 360).round
|
||||
y = ((lat.to_f + 90) * 65535 / 180).round
|
||||
|
||||
tile_for_xy(x, y)
|
||||
end
|
||||
|
||||
def self.tiles_for_area(bbox)
|
||||
minx = ((bbox.min_lon + 180) * 65535 / 360).round
|
||||
maxx = ((bbox.max_lon + 180) * 65535 / 360).round
|
||||
miny = ((bbox.min_lat + 90) * 65535 / 180).round
|
||||
maxy = ((bbox.max_lat + 90) * 65535 / 180).round
|
||||
tiles = []
|
||||
|
||||
minx.upto(maxx) do |x|
|
||||
miny.upto(maxy) do |y|
|
||||
tiles << tile_for_xy(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
tiles
|
||||
end
|
||||
|
||||
def self.tile_for_xy(x, y)
|
||||
t = 0
|
||||
|
||||
16.times do
|
||||
t = t << 1
|
||||
t |= 1 unless (x & 0x8000).zero?
|
||||
x <<= 1
|
||||
t = t << 1
|
||||
t |= 1 unless (y & 0x8000).zero?
|
||||
y <<= 1
|
||||
end
|
||||
|
||||
t
|
||||
end
|
||||
|
||||
def self.iterate_tiles_for_area(bbox)
|
||||
tiles = tiles_for_area(bbox)
|
||||
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
|
||||
end
|
||||
|
||||
def self.sql_for_area(bbox, prefix)
|
||||
sql = []
|
||||
single = []
|
||||
|
||||
iterate_tiles_for_area(bbox) do |first, last|
|
||||
if first == last
|
||||
single.push(first)
|
||||
else
|
||||
sql.push("#{prefix}tile BETWEEN #{first} AND #{last}")
|
||||
end
|
||||
end
|
||||
|
||||
sql.push("#{prefix}tile IN (#{single.join(',')})") unless single.empty?
|
||||
|
||||
"( " + sql.join(" OR ") + " )"
|
||||
end
|
||||
|
||||
private_class_method :tile_for_xy, :iterate_tiles_for_area
|
||||
end
|
3
lib/quad_tile/.gitignore
vendored
3
lib/quad_tile/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
Makefile
|
||||
quad_tile.o
|
||||
quad_tile_so.so
|
|
@ -1,5 +0,0 @@
|
|||
require "mkmf"
|
||||
|
||||
with_cflags("-std=c99 #{$CFLAGS}") do
|
||||
create_makefile("quad_tile_so")
|
||||
end
|
|
@ -1,148 +0,0 @@
|
|||
#include "ruby.h"
|
||||
#include "quad_tile.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned int *tilev;
|
||||
unsigned int tilec;
|
||||
} tilelist_t;
|
||||
|
||||
static tilelist_t tilelist_for_area(unsigned int minx, unsigned int miny, unsigned int maxx, unsigned int maxy)
|
||||
{
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
tilelist_t tl;
|
||||
unsigned int maxtilec;
|
||||
|
||||
maxtilec = 256;
|
||||
|
||||
tl.tilev = malloc(maxtilec * sizeof(unsigned int));
|
||||
tl.tilec = 0;
|
||||
|
||||
for (x = minx; x <= maxx; x++)
|
||||
{
|
||||
for (y = miny; y <= maxy; y++)
|
||||
{
|
||||
if (tl.tilec == maxtilec)
|
||||
{
|
||||
maxtilec = maxtilec * 2;
|
||||
|
||||
tl.tilev = realloc(tl.tilev, maxtilec * sizeof(unsigned int));
|
||||
}
|
||||
|
||||
tl.tilev[tl.tilec++] = xy2tile(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return tl;
|
||||
}
|
||||
|
||||
static int tile_compare(const void *ap, const void *bp)
|
||||
{
|
||||
unsigned int a = *(unsigned int *)ap;
|
||||
unsigned int b = *(unsigned int *)bp;
|
||||
|
||||
if (a < b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (a > b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE tile_for_point(VALUE self, VALUE lat, VALUE lon)
|
||||
{
|
||||
unsigned int x = lon2x(NUM2DBL(lon));
|
||||
unsigned int y = lat2y(NUM2DBL(lat));
|
||||
|
||||
return UINT2NUM(xy2tile(x, y));
|
||||
}
|
||||
|
||||
static VALUE tiles_for_area(VALUE self, VALUE bbox)
|
||||
{
|
||||
unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
|
||||
unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
|
||||
unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
|
||||
unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
|
||||
tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
|
||||
VALUE tiles = rb_ary_new();
|
||||
unsigned int t;
|
||||
|
||||
for (t = 0; t < tl.tilec; t++)
|
||||
{
|
||||
rb_ary_push(tiles, UINT2NUM(tl.tilev[t]));
|
||||
}
|
||||
|
||||
free(tl.tilev);
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
static VALUE tile_for_xy(VALUE self, VALUE x, VALUE y)
|
||||
{
|
||||
return UINT2NUM(xy2tile(NUM2UINT(x), NUM2UINT(y)));
|
||||
}
|
||||
|
||||
static VALUE iterate_tiles_for_area(VALUE self, VALUE bbox)
|
||||
{
|
||||
unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
|
||||
unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
|
||||
unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
|
||||
unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
|
||||
tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
|
||||
|
||||
if (tl.tilec > 0)
|
||||
{
|
||||
unsigned int first;
|
||||
unsigned int last;
|
||||
unsigned int t;
|
||||
VALUE a = rb_ary_new();
|
||||
|
||||
qsort(tl.tilev, tl.tilec, sizeof(unsigned int), tile_compare);
|
||||
|
||||
first = last = tl.tilev[0];
|
||||
|
||||
for (t = 1; t < tl.tilec; t++)
|
||||
{
|
||||
unsigned int tile = tl.tilev[t];
|
||||
|
||||
if (tile == last + 1)
|
||||
{
|
||||
last = tile;
|
||||
}
|
||||
else
|
||||
{
|
||||
rb_ary_store(a, 0, UINT2NUM(first));
|
||||
rb_ary_store(a, 1, UINT2NUM(last));
|
||||
rb_yield(a);
|
||||
|
||||
first = last = tile;
|
||||
}
|
||||
}
|
||||
|
||||
rb_ary_store(a, 0, UINT2NUM(first));
|
||||
rb_ary_store(a, 1, UINT2NUM(last));
|
||||
rb_yield(a);
|
||||
}
|
||||
|
||||
free(tl.tilev);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void Init_quad_tile_so(void)
|
||||
{
|
||||
VALUE m = rb_define_module("QuadTile");
|
||||
|
||||
rb_define_module_function(m, "tile_for_point", tile_for_point, 2);
|
||||
rb_define_module_function(m, "tiles_for_area", tiles_for_area, 1);
|
||||
rb_define_module_function(m, "tile_for_xy", tile_for_xy, 2);
|
||||
rb_define_module_function(m, "iterate_tiles_for_area", iterate_tiles_for_area, 1);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#include <math.h>
|
||||
|
||||
static inline unsigned int xy2tile(unsigned int x, unsigned int y)
|
||||
{
|
||||
unsigned int tile = 0;
|
||||
int i;
|
||||
|
||||
for (i = 15; i >= 0; i--)
|
||||
{
|
||||
tile = (tile << 1) | ((x >> i) & 1);
|
||||
tile = (tile << 1) | ((y >> i) & 1);
|
||||
}
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
static inline unsigned int lon2x(double lon)
|
||||
{
|
||||
return round((lon + 180.0) * 65535.0 / 360.0);
|
||||
}
|
||||
|
||||
static inline unsigned int lat2y(double lat)
|
||||
{
|
||||
return round((lat + 90.0) * 65535.0 / 180.0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue