geohash 1.0.0 → 1.0.1
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.
- data.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/README.txt +5 -1
- data/bin/geohash +1 -0
- data/geohash_native.c +54 -25
- data/lib/geohash.rb +7 -2
- data/test/test_geohash.rb +30 -1
- metadata +4 -4
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
|
Binary file
|
data/History.txt
CHANGED
data/README.txt
CHANGED
|
@@ -15,6 +15,7 @@ removing characters from the end of the code to reduce its size (and gradually l
|
|
|
15
15
|
See these resources online:
|
|
16
16
|
http://geohash.org
|
|
17
17
|
http://en.wikipedia.org/wiki/Geohash
|
|
18
|
+
http://openlocation.org/geohash/geohash-js (javascript implementation and demo)
|
|
18
19
|
|
|
19
20
|
== FEATURES/PROBLEMS:
|
|
20
21
|
|
|
@@ -29,7 +30,6 @@ GeoHash is very easy to use (and fast) because it's written in C with Ruby bindi
|
|
|
29
30
|
|
|
30
31
|
require 'rubygems'
|
|
31
32
|
require 'geohash'
|
|
32
|
-
include GeoHash
|
|
33
33
|
|
|
34
34
|
GeoHash.decode('f77')
|
|
35
35
|
=> [63.98438, -73.82813]
|
|
@@ -37,6 +37,10 @@ GeoHash is very easy to use (and fast) because it's written in C with Ruby bindi
|
|
|
37
37
|
GeoHash.encode(39.51, -76.24)
|
|
38
38
|
=> "dr1bc0edrj"
|
|
39
39
|
|
|
40
|
+
# Decode a geohash to a bounding box
|
|
41
|
+
decode_bbox('dqcw4')
|
|
42
|
+
=> [39.0234375, -76.552734375], [39.0673828125, -76.5087890625]]
|
|
43
|
+
|
|
40
44
|
You can encode or decode to an arbitrary level of precision:
|
|
41
45
|
|
|
42
46
|
# Encode latitude and longitude to a geohash with precision digits
|
data/bin/geohash
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
data/geohash_native.c
CHANGED
|
@@ -26,21 +26,22 @@
|
|
|
26
26
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
27
27
|
|
|
28
28
|
#include "ruby.h"
|
|
29
|
+
#include <ctype.h>
|
|
29
30
|
|
|
30
31
|
static VALUE rb_mGeoHash;
|
|
31
32
|
|
|
32
33
|
#define BASE32 "0123456789bcdefghjkmnpqrstuvwxyz"
|
|
33
34
|
|
|
34
|
-
void refine_interval(double *interval, char cd, char mask) {
|
|
35
|
+
static void refine_interval(double *interval, char cd, char mask) {
|
|
35
36
|
if (cd&mask)
|
|
36
37
|
interval[0] = (interval[0] + interval[1])/2;
|
|
37
|
-
|
|
38
|
+
else
|
|
38
39
|
interval[1] = (interval[0] + interval[1])/2;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
static void decode_geohash_bbox(char *geohash, double *lat, double *lon) {
|
|
42
43
|
int i, j, hashlen, is_even=1;
|
|
43
|
-
double
|
|
44
|
+
double lat_err, lon_err;
|
|
44
45
|
char c, cd, mask;
|
|
45
46
|
char bits[] = {16,8,4,2,1};
|
|
46
47
|
|
|
@@ -64,46 +65,51 @@ float *decode_geohash(char *geohash, double *point) {
|
|
|
64
65
|
is_even = !is_even;
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static void decode_geohash(char *geohash, double *point) {
|
|
71
|
+
double lat[2], lon[2];
|
|
72
|
+
|
|
73
|
+
decode_geohash_bbox(geohash, lat, lon);
|
|
67
74
|
|
|
68
75
|
point[0] = (lat[0] + lat[1]) / 2;
|
|
69
76
|
point[1] = (lon[0] + lon[1]) / 2;
|
|
70
|
-
|
|
71
|
-
return 0;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
void
|
|
79
|
+
static void encode_geohash(double latitude, double longitude, int precision, char *geohash) {
|
|
75
80
|
int is_even=1, i=0;
|
|
76
81
|
double lat[2], lon[2], mid;
|
|
77
|
-
char bits[] = {16,8,4,2,1}
|
|
82
|
+
char bits[] = {16,8,4,2,1};
|
|
83
|
+
int bit=0, ch=0;
|
|
78
84
|
|
|
79
85
|
lat[0] = -90.0; lat[1] = 90.0;
|
|
80
86
|
lon[0] = -180.0; lon[1] = 180.0;
|
|
81
87
|
|
|
82
88
|
while (i < precision) {
|
|
83
|
-
|
|
89
|
+
if (is_even) {
|
|
84
90
|
mid = (lon[0] + lon[1]) / 2;
|
|
85
|
-
|
|
91
|
+
if (longitude > mid) {
|
|
86
92
|
ch |= bits[bit];
|
|
87
93
|
lon[0] = mid;
|
|
88
|
-
|
|
94
|
+
} else
|
|
89
95
|
lon[1] = mid;
|
|
90
|
-
|
|
96
|
+
} else {
|
|
91
97
|
mid = (lat[0] + lat[1]) / 2;
|
|
92
|
-
|
|
98
|
+
if (latitude > mid) {
|
|
93
99
|
ch |= bits[bit];
|
|
94
100
|
lat[0] = mid;
|
|
95
|
-
|
|
101
|
+
} else
|
|
96
102
|
lat[1] = mid;
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
}
|
|
104
|
+
|
|
99
105
|
is_even = !is_even;
|
|
100
|
-
|
|
106
|
+
if (bit < 4)
|
|
101
107
|
bit++;
|
|
102
|
-
|
|
108
|
+
else {
|
|
103
109
|
geohash[i++] = BASE32[ch];
|
|
104
110
|
bit = 0;
|
|
105
111
|
ch = 0;
|
|
106
|
-
|
|
112
|
+
}
|
|
107
113
|
}
|
|
108
114
|
geohash[i] = 0;
|
|
109
115
|
}
|
|
@@ -124,27 +130,50 @@ static VALUE encode(VALUE self, VALUE lat, VALUE lon, VALUE precision)
|
|
|
124
130
|
encode_geohash(RFLOAT(lat)->value, RFLOAT(lon)->value, digits, str);
|
|
125
131
|
|
|
126
132
|
geohash = rb_str_new2(str);
|
|
127
|
-
|
|
133
|
+
return geohash;
|
|
128
134
|
}
|
|
129
135
|
|
|
136
|
+
static VALUE decode_bbox(VALUE self, VALUE str)
|
|
137
|
+
{
|
|
138
|
+
VALUE ary, ret;
|
|
139
|
+
double lat[2], lon[2];
|
|
140
|
+
Check_Type(str, T_STRING);
|
|
141
|
+
|
|
142
|
+
decode_geohash_bbox(RSTRING(str)->ptr, lat, lon);
|
|
143
|
+
|
|
144
|
+
ret = rb_ary_new2(2); /* [[lat[0], lon[0]], [lat[1], lon[1]]] */
|
|
145
|
+
|
|
146
|
+
ary = rb_ary_new2(2); /* [lat[0], lon[0]] */
|
|
147
|
+
rb_ary_store(ary, 0, rb_float_new(lat[0]));
|
|
148
|
+
rb_ary_store(ary, 1, rb_float_new(lon[0]));
|
|
149
|
+
rb_ary_store(ret, 0, ary);
|
|
150
|
+
|
|
151
|
+
ary = rb_ary_new2(2); /* [lat[1], lon[1]] */
|
|
152
|
+
rb_ary_store(ary, 0, rb_float_new(lat[1]));
|
|
153
|
+
rb_ary_store(ary, 1, rb_float_new(lon[1]));
|
|
154
|
+
rb_ary_store(ret, 1, ary);
|
|
155
|
+
|
|
156
|
+
return ret;
|
|
157
|
+
}
|
|
130
158
|
|
|
131
159
|
static VALUE decode(VALUE self, VALUE str)
|
|
132
160
|
{
|
|
133
161
|
VALUE ary;
|
|
134
162
|
double point[2];
|
|
135
|
-
|
|
136
|
-
|
|
163
|
+
Check_Type(str, T_STRING);
|
|
164
|
+
|
|
137
165
|
decode_geohash(RSTRING(str)->ptr, point);
|
|
138
|
-
|
|
139
|
-
|
|
166
|
+
|
|
167
|
+
ary = rb_ary_new2(2);
|
|
140
168
|
rb_ary_store(ary, 0, rb_float_new(point[0]));
|
|
141
169
|
rb_ary_store(ary, 1, rb_float_new(point[1]));
|
|
142
|
-
|
|
170
|
+
return ary;
|
|
143
171
|
}
|
|
144
172
|
|
|
145
173
|
void Init_geohash_native()
|
|
146
174
|
{
|
|
147
175
|
rb_mGeoHash = rb_define_module("GeoHash");
|
|
176
|
+
rb_define_method(rb_mGeoHash, "decode_bbox_base", decode_bbox, 1);
|
|
148
177
|
rb_define_method(rb_mGeoHash, "decode_base", decode, 1);
|
|
149
178
|
rb_define_method(rb_mGeoHash, "encode_base", encode, 3);
|
|
150
179
|
}
|
data/lib/geohash.rb
CHANGED
|
@@ -9,16 +9,21 @@ end
|
|
|
9
9
|
|
|
10
10
|
module GeoHash
|
|
11
11
|
|
|
12
|
-
VERSION = '1.0.
|
|
12
|
+
VERSION = '1.0.1'
|
|
13
13
|
|
|
14
14
|
# Encode latitude and longitude to a geohash with precision digits
|
|
15
15
|
def encode(lat, lon, precision=10)
|
|
16
16
|
encode_base(lat, lon, precision)
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
# Decode a geohash to a latitude and longitude with decimals digits
|
|
20
20
|
def decode(geohash, decimals=5)
|
|
21
21
|
lat, lon = decode_base(geohash)
|
|
22
22
|
[lat.decimals(decimals), lon.decimals(decimals)]
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
# Decode a geohash to a bounding box
|
|
26
|
+
def decode_bbox(geohash)
|
|
27
|
+
decode_bbox_base(geohash)
|
|
28
|
+
end
|
|
24
29
|
end
|
data/test/test_geohash.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
$LOAD_PATH << "#{File.dirname(__FILE__)}/.."
|
|
2
3
|
require "#{File.dirname(__FILE__)}/../lib/geohash"
|
|
3
4
|
require 'test/unit'
|
|
4
5
|
|
|
@@ -21,6 +22,34 @@ class GeoHashTest < Test::Unit::TestCase
|
|
|
21
22
|
assert_equal "6gkzmg1u", encode(-25.427, -49.315, 8)
|
|
22
23
|
assert_equal "ezs42", encode(42.60498046875, -5.60302734375, 5)
|
|
23
24
|
end
|
|
25
|
+
|
|
26
|
+
def check_decoding(gh)
|
|
27
|
+
exact = decode(gh, 20)
|
|
28
|
+
bbox = decode_bbox(gh)
|
|
29
|
+
|
|
30
|
+
# check that the bbox is centered on the decoded point
|
|
31
|
+
bbox_center = [(bbox[0][0] + bbox[1][0]) / 2, (bbox[0][1] + bbox[1][1]) / 2]
|
|
32
|
+
assert_equal exact, bbox_center
|
|
33
|
+
|
|
34
|
+
# check that the bounding box is the expected size
|
|
35
|
+
bits = gh.size * 5
|
|
36
|
+
lon_bits = (bits.to_f/2).ceil
|
|
37
|
+
lat_bits = (bits.to_f/2).floor
|
|
38
|
+
correct_size = [180.0/2**lat_bits, 360.0/2**lon_bits]
|
|
39
|
+
bbox_size = [bbox[1][0] - bbox[0][0], bbox[1][1] - bbox[0][1]]
|
|
40
|
+
assert_equal bbox_size, correct_size
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_decoding_bbox
|
|
44
|
+
s = "dqcw4bnrs6s7"
|
|
45
|
+
(s.length-1).downto(0) do |l|
|
|
46
|
+
check_decoding(s[0..l])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_specific_bbox
|
|
51
|
+
assert_equal [[39.0234375, -76.552734375], [39.0673828125, -76.5087890625]], decode_bbox('dqcw4')
|
|
52
|
+
end
|
|
24
53
|
|
|
25
54
|
# require 'benchmark'
|
|
26
55
|
# def test_multiple
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: geohash
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Troy
|
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
|
30
30
|
K80lsu167t5ZwbXh+Day+g==
|
|
31
31
|
-----END CERTIFICATE-----
|
|
32
32
|
|
|
33
|
-
date: 2008-
|
|
33
|
+
date: 2008-06-11 00:00:00 -04:00
|
|
34
34
|
default_executable:
|
|
35
35
|
dependencies:
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
@@ -40,9 +40,9 @@ dependencies:
|
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: 1.5.
|
|
43
|
+
version: 1.5.3
|
|
44
44
|
version:
|
|
45
|
-
description: "GeoHash Gem for Ruby (c) 2008 David Troy dave@roundhousetech.com Geohash is a latitude/longitude encoding system invented by Gustavo Niemeyer when writing the web service at geohash.org, and put into the public domain. Geohashes offer properties like arbitrary precision, similar prefixes for nearby positions, and the possibility of gradually removing characters from the end of the code to reduce its size (and gradually lose precision). See these resources online: http://geohash.org http://en.wikipedia.org/wiki/Geohash"
|
|
45
|
+
description: "GeoHash Gem for Ruby (c) 2008 David Troy dave@roundhousetech.com Geohash is a latitude/longitude encoding system invented by Gustavo Niemeyer when writing the web service at geohash.org, and put into the public domain. Geohashes offer properties like arbitrary precision, similar prefixes for nearby positions, and the possibility of gradually removing characters from the end of the code to reduce its size (and gradually lose precision). See these resources online: http://geohash.org http://en.wikipedia.org/wiki/Geohash http://openlocation.org/geohash/geohash-js (javascript implementation and demo)"
|
|
46
46
|
email:
|
|
47
47
|
- dave@roundhousetech.com
|
|
48
48
|
executables:
|
metadata.gz.sig
CHANGED
|
Binary file
|