geokit 1.8.3 → 1.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/geokit.gemspec +1 -0
- data/lib/geokit/geocoders.rb +9 -10
- data/lib/geokit/geocoders/bing.rb +1 -1
- data/lib/geokit/geocoders/google.rb +16 -11
- data/lib/geokit/geocoders/ip.rb +1 -1
- data/lib/geokit/mappable.rb +3 -5
- data/lib/geokit/net_adapter/net_http.rb +21 -0
- data/lib/geokit/net_adapter/typhoeus.rb +13 -0
- data/lib/geokit/polygon.rb +15 -21
- data/lib/geokit/version.rb +1 -1
- data/test/helper.rb +5 -1
- data/test/test_mappable.rb +12 -0
- data/test/test_net_adapter.rb +46 -0
- data/test/test_polygon_contains.rb +2 -2
- metadata +26 -4
data/CHANGELOG.md
CHANGED
data/geokit.gemspec
CHANGED
data/lib/geokit/geocoders.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
require 'geokit/net_adapter/net_http'
|
3
|
+
require 'geokit/net_adapter/typhoeus'
|
2
4
|
require 'ipaddr'
|
3
5
|
require 'rexml/document'
|
4
6
|
require 'yaml'
|
@@ -37,6 +39,7 @@ module Geokit
|
|
37
39
|
@@logger=Logger.new(STDOUT)
|
38
40
|
@@logger.level=Logger::INFO
|
39
41
|
@@domain = nil
|
42
|
+
@@net_adapter = Geokit::NetAdapter::NetHttp
|
40
43
|
|
41
44
|
def self.__define_accessors
|
42
45
|
class_variables.each do |v|
|
@@ -141,15 +144,11 @@ module Geokit
|
|
141
144
|
|
142
145
|
# Wraps the geocoder call around a proxy if necessary.
|
143
146
|
def self.do_get(url)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
proxy_uri = URI.parse(proxy_uri_string)
|
150
|
-
net_http_args += [proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
|
151
|
-
end
|
152
|
-
Net::HTTP::new(*net_http_args).start { |http| http.request(req) }
|
147
|
+
net_adapter.do_get(url)
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.net_adapter
|
151
|
+
Geokit::Geocoders::net_adapter
|
153
152
|
end
|
154
153
|
|
155
154
|
def self.provider_name
|
@@ -174,7 +173,7 @@ module Geokit
|
|
174
173
|
|
175
174
|
def self.process(format, url, *args)
|
176
175
|
res = call_geocoder_service(url)
|
177
|
-
return GeoLoc.new
|
176
|
+
return GeoLoc.new unless net_adapter.success?(res)
|
178
177
|
parse format, res.body, *args
|
179
178
|
end
|
180
179
|
|
@@ -11,7 +11,7 @@ module Geokit
|
|
11
11
|
def self.do_geocode(address)
|
12
12
|
url = submit_url(address)
|
13
13
|
res = call_geocoder_service(url)
|
14
|
-
return GeoLoc.new
|
14
|
+
return GeoLoc.new unless net_adapter.success?(res)
|
15
15
|
xml = transcode_to_utf8(res.body)
|
16
16
|
parse :xml, xml
|
17
17
|
end
|
@@ -140,36 +140,41 @@ module Geokit
|
|
140
140
|
loc.lat = ll['lat'].to_f
|
141
141
|
loc.lng = ll['lng'].to_f
|
142
142
|
|
143
|
+
set_bounds(loc, addr)
|
144
|
+
|
145
|
+
loc
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.set_bounds(loc, addr)
|
143
149
|
viewport = addr['geometry']['viewport']
|
144
150
|
ne = Geokit::LatLng.from_json(viewport['northeast'])
|
145
151
|
sw = Geokit::LatLng.from_json(viewport['southwest'])
|
146
152
|
loc.suggested_bounds = Geokit::Bounds.new(sw, ne)
|
147
|
-
|
148
|
-
loc
|
149
153
|
end
|
150
154
|
|
151
155
|
def self.set_address_components(loc, addr)
|
152
156
|
addr['address_components'].each do |comp|
|
157
|
+
types = comp['types']
|
153
158
|
case
|
154
|
-
when
|
159
|
+
when types.include?("subpremise")
|
155
160
|
loc.sub_premise = comp['short_name']
|
156
|
-
when
|
161
|
+
when types.include?("street_number")
|
157
162
|
loc.street_number = comp['short_name']
|
158
|
-
when
|
163
|
+
when types.include?("route")
|
159
164
|
loc.street_name = comp['long_name']
|
160
|
-
when
|
165
|
+
when types.include?("locality")
|
161
166
|
loc.city = comp['long_name']
|
162
|
-
when
|
167
|
+
when types.include?("administrative_area_level_1")
|
163
168
|
loc.state = comp['short_name']
|
164
169
|
loc.province = comp['short_name']
|
165
|
-
when
|
170
|
+
when types.include?("postal_code")
|
166
171
|
loc.zip = comp['long_name']
|
167
|
-
when
|
172
|
+
when types.include?("country")
|
168
173
|
loc.country_code = comp['short_name']
|
169
174
|
loc.country = comp['long_name']
|
170
|
-
when
|
175
|
+
when types.include?("administrative_area_level_2")
|
171
176
|
loc.district = comp['long_name']
|
172
|
-
when
|
177
|
+
when types.include?('neighborhood')
|
173
178
|
loc.neighborhood = comp['short_name']
|
174
179
|
end
|
175
180
|
end
|
data/lib/geokit/geocoders/ip.rb
CHANGED
@@ -13,7 +13,7 @@ module Geokit
|
|
13
13
|
return GeoLoc.new unless valid_ip?(ip)
|
14
14
|
url = submit_url(ip)
|
15
15
|
res = call_geocoder_service(url)
|
16
|
-
return GeoLoc.new
|
16
|
+
return GeoLoc.new unless net_adapter.success?(res)
|
17
17
|
ensure_utf8_encoding(res)
|
18
18
|
body = res.body
|
19
19
|
body = body.encode('UTF-8') if body.respond_to? :encode
|
data/lib/geokit/mappable.rb
CHANGED
@@ -60,12 +60,10 @@ module Geokit
|
|
60
60
|
Math.sqrt(lat_length ** 2 + lng_length ** 2)
|
61
61
|
end
|
62
62
|
|
63
|
+
# Ruby 1.9 raises {Math::DomainError}, but it is not defined in Ruby 1.8
|
63
64
|
def math_error_classes
|
64
|
-
|
65
|
-
|
66
|
-
# Ruby 1.9 raises {Math::DomainError}, but it is not defined in Ruby
|
67
|
-
# 1.8. Backwards-compatibly rescue both errors.
|
68
|
-
error_classes << Math::DomainError if defined?(Math::DomainError)
|
65
|
+
return [Errno::EDOM, Math::DomainError] if defined?(Math::DomainError)
|
66
|
+
[Errno::EDOM]
|
69
67
|
end
|
70
68
|
|
71
69
|
# Returns heading in degrees (0 is north, 90 is east, 180 is south, etc)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Geokit
|
2
|
+
module NetAdapter
|
3
|
+
class NetHttp
|
4
|
+
def self.do_get(url)
|
5
|
+
uri = URI.parse(url)
|
6
|
+
req = Net::HTTP::Get.new(url)
|
7
|
+
req.basic_auth(uri.user, uri.password) if uri.userinfo
|
8
|
+
net_http_args = [uri.host, uri.port]
|
9
|
+
if (proxy_uri_string = Geokit::Geocoders::proxy)
|
10
|
+
proxy_uri = URI.parse(proxy_uri_string)
|
11
|
+
net_http_args += [proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
|
12
|
+
end
|
13
|
+
Net::HTTP::new(*net_http_args).start { |http| http.request(req) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.success?(response)
|
17
|
+
response.is_a?(Net::HTTPSuccess)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/geokit/polygon.rb
CHANGED
@@ -2,42 +2,36 @@ module Geokit
|
|
2
2
|
# A complex polygon made of multiple points. End point must equal start point to close the poly.
|
3
3
|
class Polygon
|
4
4
|
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :points
|
6
6
|
|
7
|
+
# Pass in an array of Geokit::LatLng
|
7
8
|
def initialize(points)
|
8
|
-
|
9
|
-
@poly_x = []
|
10
|
-
@poly_y = []
|
11
|
-
|
12
|
-
points.each do |point|
|
13
|
-
@poly_x << point.lng
|
14
|
-
@poly_y << point.lat
|
15
|
-
end
|
9
|
+
@points = points
|
16
10
|
|
17
11
|
# A Polygon must be 'closed', the last point equal to the first point
|
18
|
-
|
19
|
-
|
20
|
-
@poly_x << @poly_x[0]
|
21
|
-
@poly_y << @poly_y[0]
|
22
|
-
end
|
23
|
-
|
12
|
+
# Append the first point to the array to close the polygon
|
13
|
+
@points << points[0] if points[0] != points[-1]
|
24
14
|
end
|
25
15
|
|
26
16
|
def contains?(point)
|
27
|
-
|
17
|
+
last_point = @points[-1]
|
28
18
|
oddNodes = false
|
29
19
|
x = point.lng
|
30
20
|
y = point.lat
|
31
21
|
|
32
|
-
for
|
33
|
-
|
34
|
-
|
35
|
-
|
22
|
+
for p in @points
|
23
|
+
yi = p.lat
|
24
|
+
xi = p.lng
|
25
|
+
yj = last_point.lat
|
26
|
+
xj = last_point.lng
|
27
|
+
if (yi < y && yj >= y ||
|
28
|
+
yj < y && yi >= y)
|
29
|
+
if (xi + (y - yi) / (yj - yi) * (xj - xi) < x)
|
36
30
|
oddNodes = !oddNodes
|
37
31
|
end
|
38
32
|
end
|
39
33
|
|
40
|
-
|
34
|
+
last_point = p
|
41
35
|
end
|
42
36
|
|
43
37
|
oddNodes
|
data/lib/geokit/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -11,7 +11,7 @@ end
|
|
11
11
|
require 'geoip'
|
12
12
|
|
13
13
|
if ENV['COVERAGE']
|
14
|
-
COVERAGE_THRESHOLD =
|
14
|
+
COVERAGE_THRESHOLD = 91
|
15
15
|
require 'simplecov'
|
16
16
|
require 'simplecov-rcov'
|
17
17
|
require 'coveralls'
|
@@ -42,6 +42,10 @@ class MockSuccess < Net::HTTPSuccess #:nodoc: all
|
|
42
42
|
def initialize
|
43
43
|
@header = {}
|
44
44
|
end
|
45
|
+
|
46
|
+
def success? # Typhoeus
|
47
|
+
true
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
class MockFailure < Net::HTTPServiceUnavailable #:nodoc: all
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
|
3
|
+
class MappableTest < Test::Unit::TestCase #:nodoc: all
|
4
|
+
|
5
|
+
def test_math_error_classes
|
6
|
+
error_case = 0.49 * 180
|
7
|
+
from = Geokit::LatLng.new(error_case, error_case)
|
8
|
+
to = Geokit::LatLng.new(error_case, error_case)
|
9
|
+
assert_equal 0.0, Geokit::LatLng.distance_between_sphere(from, to, :kms)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
|
3
|
+
# Base class for testing geocoders.
|
4
|
+
class NetAdapterTest < Test::Unit::TestCase #:nodoc: all
|
5
|
+
class Geokit::Geocoders::CachedGeocoder < Geokit::Geocoders::Geocoder
|
6
|
+
def self.parse_json(hash)
|
7
|
+
hash
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class SuperSimpleCache
|
12
|
+
def initialize
|
13
|
+
@cache = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(key, value)
|
17
|
+
@cache[key] = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch(key)
|
21
|
+
@cache[key]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
RESULT = '{"name":"json"}'
|
26
|
+
RESULT_HASH = {"name" => "json"}
|
27
|
+
|
28
|
+
# Defines common test fixtures.
|
29
|
+
def setup
|
30
|
+
@url = 'http://www.cacheme.com'
|
31
|
+
@address = 'San Francisco, CA'
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_cache
|
35
|
+
old_adapter = Geokit::Geocoders::net_adapter
|
36
|
+
Geokit::Geocoders::net_adapter = Geokit::NetAdapter::Typhoeus
|
37
|
+
Typhoeus::Config.cache = SuperSimpleCache
|
38
|
+
success = MockSuccess.new
|
39
|
+
success.expects(:body).returns(RESULT)
|
40
|
+
url = 'http://www.cacheme.com'
|
41
|
+
Geokit::NetAdapter::Typhoeus.expects(:do_get).with(@url).returns(success)
|
42
|
+
assert_equal RESULT_HASH, Geokit::Geocoders::CachedGeocoder.process(:json, @url)
|
43
|
+
Typhoeus::Config.cache = nil
|
44
|
+
Geokit::Geocoders::net_adapter = old_adapter
|
45
|
+
end
|
46
|
+
end
|
@@ -93,8 +93,8 @@ class PolygonTest < Test::Unit::TestCase #:nodoc: all
|
|
93
93
|
#puts "\t Does poly_x[0] (#{@open_polygon.poly_x[0]}) == poly_x[-1] (#{@open_polygon.poly_x[-1]}) ?"
|
94
94
|
#puts "\t Does poly_y[0] (#{@open_polygon.poly_y[0]}) == poly_y[-1] (#{@open_polygon.poly_y[-1]}) ?"
|
95
95
|
|
96
|
-
assert @open_polygon.
|
97
|
-
assert @open_polygon.
|
96
|
+
assert @open_polygon.points[0].lng == @open_polygon.points[-1].lng
|
97
|
+
assert @open_polygon.points[0].lat == @open_polygon.points[-1].lat
|
98
98
|
|
99
99
|
end
|
100
100
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geokit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2014-01-12 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: multi_json
|
@@ -158,6 +158,22 @@ dependencies:
|
|
158
158
|
- - ! '>='
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: '0'
|
161
|
+
- !ruby/object:Gem::Dependency
|
162
|
+
name: typhoeus
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
type: :development
|
170
|
+
prerelease: false
|
171
|
+
version_requirements: !ruby/object:Gem::Requirement
|
172
|
+
none: false
|
173
|
+
requirements:
|
174
|
+
- - ! '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
161
177
|
description: Geokit provides geocoding and distance calculation in an easy-to-use
|
162
178
|
API
|
163
179
|
email:
|
@@ -220,6 +236,8 @@ files:
|
|
220
236
|
- lib/geokit/lat_lng.rb
|
221
237
|
- lib/geokit/mappable.rb
|
222
238
|
- lib/geokit/multi_geocoder.rb
|
239
|
+
- lib/geokit/net_adapter/net_http.rb
|
240
|
+
- lib/geokit/net_adapter/typhoeus.rb
|
223
241
|
- lib/geokit/polygon.rb
|
224
242
|
- lib/geokit/version.rb
|
225
243
|
- test/helper.rb
|
@@ -236,9 +254,11 @@ files:
|
|
236
254
|
- test/test_inflector.rb
|
237
255
|
- test/test_ipgeocoder.rb
|
238
256
|
- test/test_latlng.rb
|
257
|
+
- test/test_mappable.rb
|
239
258
|
- test/test_maxmind_geocoder.rb
|
240
259
|
- test/test_multi_geocoder.rb
|
241
260
|
- test/test_multi_ip_geocoder.rb
|
261
|
+
- test/test_net_adapter.rb
|
242
262
|
- test/test_openstreetmap_geocoder.rb
|
243
263
|
- test/test_polygon_contains.rb
|
244
264
|
- test/test_ripe_geocoder.rb
|
@@ -262,7 +282,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
262
282
|
version: '0'
|
263
283
|
segments:
|
264
284
|
- 0
|
265
|
-
hash: -
|
285
|
+
hash: -1117828600571501675
|
266
286
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
287
|
none: false
|
268
288
|
requirements:
|
@@ -271,7 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
271
291
|
version: '0'
|
272
292
|
segments:
|
273
293
|
- 0
|
274
|
-
hash: -
|
294
|
+
hash: -1117828600571501675
|
275
295
|
requirements: []
|
276
296
|
rubyforge_project:
|
277
297
|
rubygems_version: 1.8.25
|
@@ -293,9 +313,11 @@ test_files:
|
|
293
313
|
- test/test_inflector.rb
|
294
314
|
- test/test_ipgeocoder.rb
|
295
315
|
- test/test_latlng.rb
|
316
|
+
- test/test_mappable.rb
|
296
317
|
- test/test_maxmind_geocoder.rb
|
297
318
|
- test/test_multi_geocoder.rb
|
298
319
|
- test/test_multi_ip_geocoder.rb
|
320
|
+
- test/test_net_adapter.rb
|
299
321
|
- test/test_openstreetmap_geocoder.rb
|
300
322
|
- test/test_polygon_contains.rb
|
301
323
|
- test/test_ripe_geocoder.rb
|