quad_tile 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c40edff7edcbb1958d16f9bf2353ce16c8c83900cda9f3ae5d7f8be9c84a6c75
4
+ data.tar.gz: f09d21cf909290977fe522ba15d2b0db78364fcdfca8ac41201b5e7132a8b562
5
+ SHA512:
6
+ metadata.gz: cff3d09b7bb3483fc0d7cdd2470e71c232c08bd248f4151db291329a37a6fde18f54d5e2d2564059bc7f4463a60eb39e6e9d116ba9dc8bb90108efe40b2c2c51
7
+ data.tar.gz: 44878ba207ea1fc0b51983b9742594f4e991102aea4fa990c67fa3586085eeb3283c77c0131ae90edddabc09a5c8c1c0a8c8f4a18075d78240d01b12120a6e5d
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Quad Tile
2
+
3
+ Gem bundle of native C extensions to `QuadTile` module from [openstreetmap](https://github.com/openstreetmap/openstreetmap-website)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'quad_tile'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install quad_tile
20
+
21
+ ## Usage
22
+
23
+ This primary functions from C exposed to the `QuadTile` module in ruby are `.tile_for_point` and `tiles_for_area`.
24
+
25
+ ```ruby
26
+
27
+ QuadTile.tile_for_point(51.0, 1.0)
28
+ #=> 3493907048
29
+
30
+ # Build an object with min_lon, min_lat, max_lon, max_lon instance varialbes. In OSM
31
+ # this is an instance of BoundingBox
32
+ box = BoundingBox.new(min_lon: 0.99, min_lat: 50.99, max_lon: 1.01, max_lat: 51.01)
33
+
34
+ QuadTile.tiles_for_area(box)
35
+ #=> [3493906992, 3493906993, 3493906996, 3493906997, 3493907040, 3493907041, 3493907044, 3493907045, 3493906994, 3493906995, 3493906998, 3493906999, 3493907042, 3493907043, 3493907046, 3493907047, 3493907000, 3493907001, 3493907004, 3493907005, 3493907048, 3493907049, 3493907052, 3493907053, 3493907002, 3493907003, 3493907006, 3493907007, 3493907050, 3493907051, 3493907054, 3493907055]
36
+
37
+ ```
38
+
39
+ ## Development
40
+
41
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
42
+
43
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
44
+
45
+ ## Contributing
46
+
47
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rubyforgood/quad_tile. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
48
+
49
+ ## License
50
+
51
+ The gem is available as open source under the terms of the [GPLv2 License](http://opensource.org/licenses/GPL-2.0).
52
+
53
+ ## Code of Conduct
54
+
55
+ Everyone interacting in the Quad Tile project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rubyforgood/quad_tile/bextextlob/master/CODE_OF_CONDUCT.md).
56
+
57
+ Made with :heart: at [Ruby for Good](https://rubyforgood.org/)
@@ -0,0 +1,5 @@
1
+ require "mkmf"
2
+
3
+ with_cflags("-std=c99 #{$CFLAGS}") do
4
+ create_makefile("quad_tile/quad_tile")
5
+ end
@@ -0,0 +1,148 @@
1
+ #include "ruby.h"
2
+ #include "quad_tile.h"
3
+
4
+ typedef struct {
5
+ unsigned int *tilev;
6
+ unsigned int tilec;
7
+ } tilelist_t;
8
+
9
+ static tilelist_t tilelist_for_area(unsigned int minx, unsigned int miny, unsigned int maxx, unsigned int maxy)
10
+ {
11
+ unsigned int x;
12
+ unsigned int y;
13
+ tilelist_t tl;
14
+ unsigned int maxtilec;
15
+
16
+ maxtilec = 256;
17
+
18
+ tl.tilev = malloc(maxtilec * sizeof(unsigned int));
19
+ tl.tilec = 0;
20
+
21
+ for (x = minx; x <= maxx; x++)
22
+ {
23
+ for (y = miny; y <= maxy; y++)
24
+ {
25
+ if (tl.tilec == maxtilec)
26
+ {
27
+ maxtilec = maxtilec * 2;
28
+
29
+ tl.tilev = realloc(tl.tilev, maxtilec * sizeof(unsigned int));
30
+ }
31
+
32
+ tl.tilev[tl.tilec++] = xy2tile(x, y);
33
+ }
34
+ }
35
+
36
+ return tl;
37
+ }
38
+
39
+ static int tile_compare(const void *ap, const void *bp)
40
+ {
41
+ unsigned int a = *(unsigned int *)ap;
42
+ unsigned int b = *(unsigned int *)bp;
43
+
44
+ if (a < b)
45
+ {
46
+ return -1;
47
+ }
48
+ else if (a > b)
49
+ {
50
+ return 1;
51
+ }
52
+ else
53
+ {
54
+ return 0;
55
+ }
56
+ }
57
+
58
+ static VALUE tile_for_point(VALUE self, VALUE lat, VALUE lon)
59
+ {
60
+ unsigned int x = lon2x(NUM2DBL(lon));
61
+ unsigned int y = lat2y(NUM2DBL(lat));
62
+
63
+ return UINT2NUM(xy2tile(x, y));
64
+ }
65
+
66
+ static VALUE tiles_for_area(VALUE self, VALUE bbox)
67
+ {
68
+ unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
69
+ unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
70
+ unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
71
+ unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
72
+ tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
73
+ VALUE tiles = rb_ary_new();
74
+ unsigned int t;
75
+
76
+ for (t = 0; t < tl.tilec; t++)
77
+ {
78
+ rb_ary_push(tiles, UINT2NUM(tl.tilev[t]));
79
+ }
80
+
81
+ free(tl.tilev);
82
+
83
+ return tiles;
84
+ }
85
+
86
+ static VALUE tile_for_xy(VALUE self, VALUE x, VALUE y)
87
+ {
88
+ return UINT2NUM(xy2tile(NUM2UINT(x), NUM2UINT(y)));
89
+ }
90
+
91
+ static VALUE iterate_tiles_for_area(VALUE self, VALUE bbox)
92
+ {
93
+ unsigned int minx = lon2x(NUM2DBL(rb_iv_get(bbox, "@min_lon")));
94
+ unsigned int maxx = lon2x(NUM2DBL(rb_iv_get(bbox, "@max_lon")));
95
+ unsigned int miny = lat2y(NUM2DBL(rb_iv_get(bbox, "@min_lat")));
96
+ unsigned int maxy = lat2y(NUM2DBL(rb_iv_get(bbox, "@max_lat")));
97
+ tilelist_t tl = tilelist_for_area(minx, miny, maxx, maxy);
98
+
99
+ if (tl.tilec > 0)
100
+ {
101
+ unsigned int first;
102
+ unsigned int last;
103
+ unsigned int t;
104
+ VALUE a = rb_ary_new();
105
+
106
+ qsort(tl.tilev, tl.tilec, sizeof(unsigned int), tile_compare);
107
+
108
+ first = last = tl.tilev[0];
109
+
110
+ for (t = 1; t < tl.tilec; t++)
111
+ {
112
+ unsigned int tile = tl.tilev[t];
113
+
114
+ if (tile == last + 1)
115
+ {
116
+ last = tile;
117
+ }
118
+ else
119
+ {
120
+ rb_ary_store(a, 0, UINT2NUM(first));
121
+ rb_ary_store(a, 1, UINT2NUM(last));
122
+ rb_yield(a);
123
+
124
+ first = last = tile;
125
+ }
126
+ }
127
+
128
+ rb_ary_store(a, 0, UINT2NUM(first));
129
+ rb_ary_store(a, 1, UINT2NUM(last));
130
+ rb_yield(a);
131
+ }
132
+
133
+ free(tl.tilev);
134
+
135
+ return Qnil;
136
+ }
137
+
138
+ void Init_quad_tile(void)
139
+ {
140
+ VALUE m = rb_define_module("QuadTile");
141
+
142
+ rb_define_module_function(m, "tile_for_point", tile_for_point, 2);
143
+ rb_define_module_function(m, "tiles_for_area", tiles_for_area, 1);
144
+ rb_define_module_function(m, "tile_for_xy", tile_for_xy, 2);
145
+ rb_define_module_function(m, "iterate_tiles_for_area", iterate_tiles_for_area, 1);
146
+
147
+ return;
148
+ }
@@ -0,0 +1,3 @@
1
+ module QuadTile
2
+ VERSION = "1.0.0"
3
+ end
data/lib/quad_tile.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "quad_tile/version"
2
+ require "quad_tile/quad_tile"
3
+
4
+ module QuadTile
5
+ def self.sql_for_area(bbox, prefix)
6
+ sql = []
7
+ single = []
8
+
9
+ iterate_tiles_for_area(bbox) do |first, last|
10
+ if first == last
11
+ single.push(first)
12
+ else
13
+ sql.push("#{prefix}tile BETWEEN #{first} AND #{last}")
14
+ end
15
+ end
16
+
17
+ sql.push("#{prefix}tile IN (#{single.join(',')})") unless single.empty?
18
+
19
+ "( " + sql.join(" OR ") + " )"
20
+ end
21
+
22
+ private_class_method :tile_for_xy, :iterate_tiles_for_area
23
+ end
@@ -0,0 +1,82 @@
1
+ require_relative "test_helper"
2
+
3
+ class QuadTileTest < Minitest::Test
4
+ def test_tile_for_point
5
+ assert_equal 3493907048, QuadTile.tile_for_point(51.0, 1.0)
6
+ assert_equal 3493908088, QuadTile.tile_for_point(51.1, 1.0)
7
+ assert_equal 3493913808, QuadTile.tile_for_point(51.1, 1.1)
8
+ assert_equal 1221887424, QuadTile.tile_for_point(10.0, -123.0)
9
+ assert_equal 2147483648, QuadTile.tile_for_point(-90.0, 0.0)
10
+ end
11
+
12
+ def test_tiles_for_area
13
+ assert_equal [3493906992, 3493906993, 3493906996, 3493906997,
14
+ 3493907040, 3493907041, 3493907044, 3493907045,
15
+ 3493906994, 3493906995, 3493906998, 3493906999,
16
+ 3493907042, 3493907043, 3493907046, 3493907047,
17
+ 3493907000, 3493907001, 3493907004, 3493907005,
18
+ 3493907048, 3493907049, 3493907052, 3493907053,
19
+ 3493907002, 3493907003, 3493907006, 3493907007,
20
+ 3493907050, 3493907051, 3493907054, 3493907055],
21
+ QuadTile.tiles_for_area(BoundingBox.new(0.99, 50.99, 1.01, 51.01))
22
+ assert_equal [3493908065, 3493908068, 3493908069, 3493908080,
23
+ 3493908081, 3493908084, 3493908085, 3493908256,
24
+ 3493908067, 3493908070, 3493908071, 3493908082,
25
+ 3493908083, 3493908086, 3493908087, 3493908258,
26
+ 3493908073, 3493908076, 3493908077, 3493908088,
27
+ 3493908089, 3493908092, 3493908093, 3493908264,
28
+ 3493908075, 3493908078, 3493908079, 3493908090,
29
+ 3493908091, 3493908094, 3493908095, 3493908266],
30
+ QuadTile.tiles_for_area(BoundingBox.new(0.99, 51.09, 1.01, 51.11))
31
+ assert_equal [3493913705, 3493913708, 3493913709, 3493913720,
32
+ 3493913721, 3493913724, 3493913725, 3493913896,
33
+ 3493913707, 3493913710, 3493913711, 3493913722,
34
+ 3493913723, 3493913726, 3493913727, 3493913898,
35
+ 3493913793, 3493913796, 3493913797, 3493913808,
36
+ 3493913809, 3493913812, 3493913813, 3493913984,
37
+ 3493913795, 3493913798, 3493913799, 3493913810,
38
+ 3493913811, 3493913814, 3493913815, 3493913986,
39
+ 3493913801, 3493913804, 3493913805, 3493913816,
40
+ 3493913817, 3493913820, 3493913821, 3493913992],
41
+ QuadTile.tiles_for_area(BoundingBox.new(1.09, 51.09, 1.11, 51.11))
42
+ assert_equal [3509256924, 3509256925, 3509257096, 3509257097,
43
+ 3509257100, 3509257101, 3509257112, 3509257113,
44
+ 3509256926, 3509256927, 3509257098, 3509257099,
45
+ 3509257102, 3509257103, 3509257114, 3509257115,
46
+ 3509256948, 3509256949, 3509257120, 3509257121,
47
+ 3509257124, 3509257125, 3509257136, 3509257137,
48
+ 3509256950, 3509256951, 3509257122, 3509257123,
49
+ 3509257126, 3509257127, 3509257138, 3509257139,
50
+ 3509256956, 3509256957, 3509257128, 3509257129,
51
+ 3509257132, 3509257133, 3509257144, 3509257145],
52
+ QuadTile.tiles_for_area(BoundingBox.new(9.99, -123.01, 10.01, -122.99))
53
+ assert_equal [1252698792, 1252698793, 1252698796, 1252698797,
54
+ 1252698794, 1252698795, 1252698798, 1252698799,
55
+ 1610612736, 1610612737, 1610612740, 1610612741,
56
+ 1610612738, 1610612739, 1610612742, 1610612743,
57
+ 1610612744, 1610612745, 1610612748, 1610612749],
58
+ QuadTile.tiles_for_area(BoundingBox.new(-90.01, 0.0, -89.99, 0.01))
59
+ end
60
+
61
+ def test_sql_for_area
62
+ assert_equal "( tile BETWEEN 3493906992 AND 3493907007 OR tile BETWEEN 3493907040 AND 3493907055 )",
63
+ QuadTile.sql_for_area(BoundingBox.new(0.99, 50.99, 1.01, 51.01), "")
64
+ assert_equal "( tile BETWEEN 3493908067 AND 3493908071 OR tile BETWEEN 3493908075 AND 3493908095"\
65
+ " OR tile IN (3493908065,3493908073,3493908256,3493908258,3493908264,3493908266) )",
66
+ QuadTile.sql_for_area(BoundingBox.new(0.99, 51.09, 1.01, 51.11), "")
67
+ assert_equal "( tile BETWEEN 3493913707 AND 3493913711 OR tile BETWEEN 3493913720 AND 3493913727"\
68
+ " OR tile BETWEEN 3493913795 AND 3493913799 OR tile BETWEEN 3493913804 AND 3493913805"\
69
+ " OR tile BETWEEN 3493913808 AND 3493913817 OR tile BETWEEN 3493913820 AND 3493913821"\
70
+ " OR tile IN (3493913705,3493913793,3493913801,3493913896,3493913898,3493913984,3493913986,3493913992) )",
71
+ QuadTile.sql_for_area(BoundingBox.new(1.09, 51.09, 1.11, 51.11), "")
72
+ assert_equal "( tile BETWEEN 3509256924 AND 3509256927 OR tile BETWEEN 3509256948 AND 3509256951"\
73
+ " OR tile BETWEEN 3509256956 AND 3509256957 OR tile BETWEEN 3509257096 AND 3509257103"\
74
+ " OR tile BETWEEN 3509257112 AND 3509257115 OR tile BETWEEN 3509257120 AND 3509257129"\
75
+ " OR tile BETWEEN 3509257132 AND 3509257133 OR tile BETWEEN 3509257136 AND 3509257139"\
76
+ " OR tile BETWEEN 3509257144 AND 3509257145 )",
77
+ QuadTile.sql_for_area(BoundingBox.new(9.99, -123.01, 10.01, -122.99), "")
78
+ assert_equal "( tile BETWEEN 1252698792 AND 1252698799 OR tile BETWEEN 1610612736 AND 1610612745"\
79
+ " OR tile BETWEEN 1610612748 AND 1610612749 )",
80
+ QuadTile.sql_for_area(BoundingBox.new(-90.01, 0.0, -89.99, 0.01), "")
81
+ end
82
+ end
@@ -0,0 +1,15 @@
1
+ require "bundler/setup"
2
+ require "quad_tile"
3
+ require "minitest/autorun"
4
+ require "minitest/pride"
5
+
6
+ class BoundingBox
7
+ attr_reader :min_lon, :min_lat, :max_lon, :max_lat
8
+
9
+ def initialize(min_lon, min_lat, max_lon, max_lat)
10
+ @min_lon = min_lon.to_f unless min_lon.nil?
11
+ @min_lat = min_lat.to_f unless min_lat.nil?
12
+ @max_lon = max_lon.to_f unless max_lon.nil?
13
+ @max_lat = max_lat.to_f unless max_lat.nil?
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quad_tile
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Reynolds
8
+ - Tom Hughes
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2018-06-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.15'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.15'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '12.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '12.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: minitest
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '5'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '5'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake-compiler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description:
71
+ email:
72
+ - breyno127@gmail.com
73
+ - tom@compton.nu
74
+ executables: []
75
+ extensions:
76
+ - ext/quad_tile/extconf.rb
77
+ extra_rdoc_files: []
78
+ files:
79
+ - README.md
80
+ - ext/quad_tile/extconf.rb
81
+ - ext/quad_tile/quad_tile.c
82
+ - lib/quad_tile.rb
83
+ - lib/quad_tile/version.rb
84
+ - test/quad_tile_test.rb
85
+ - test/test_helper.rb
86
+ homepage: https://github.com/openstreetmap/quad_tile
87
+ licenses:
88
+ - GPL-2.0
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.7.6
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: native implementation of osm quad_tile functions
110
+ test_files: []