quad_tile 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []