graticule 0.1.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.
Files changed (45) hide show
  1. data/CHANGELOG.txt +8 -0
  2. data/LICENSE.txt +30 -0
  3. data/Manifest.txt +44 -0
  4. data/README.txt +10 -0
  5. data/Rakefile +16 -0
  6. data/init.rb +2 -0
  7. data/lib/graticule.rb +14 -0
  8. data/lib/graticule/distance.rb +24 -0
  9. data/lib/graticule/distance/haversine.rb +65 -0
  10. data/lib/graticule/distance/spherical.rb +30 -0
  11. data/lib/graticule/distance/vincenty.rb +99 -0
  12. data/lib/graticule/geocoder.rb +26 -0
  13. data/lib/graticule/geocoders/bogus.rb +12 -0
  14. data/lib/graticule/geocoders/geocoder_us.rb +45 -0
  15. data/lib/graticule/geocoders/google.rb +96 -0
  16. data/lib/graticule/geocoders/meta_carta.rb +102 -0
  17. data/lib/graticule/geocoders/rest.rb +98 -0
  18. data/lib/graticule/geocoders/yahoo.rb +101 -0
  19. data/lib/graticule/location.rb +28 -0
  20. data/lib/graticule/version.rb +3 -0
  21. data/test/fixtures/responses/geocoder_us/success.xml +10 -0
  22. data/test/fixtures/responses/geocoder_us/unknown.xml +1 -0
  23. data/test/fixtures/responses/google/badkey.xml +10 -0
  24. data/test/fixtures/responses/google/limit.xml +10 -0
  25. data/test/fixtures/responses/google/missing_address.xml +10 -0
  26. data/test/fixtures/responses/google/server_error.xml +10 -0
  27. data/test/fixtures/responses/google/success.xml +37 -0
  28. data/test/fixtures/responses/google/unavailable.xml +10 -0
  29. data/test/fixtures/responses/google/unknown_address.xml +10 -0
  30. data/test/fixtures/responses/meta_carta/bad_address.xml +9 -0
  31. data/test/fixtures/responses/meta_carta/multiple.xml +33 -0
  32. data/test/fixtures/responses/meta_carta/success.xml +23 -0
  33. data/test/fixtures/responses/yahoo/success.xml +3 -0
  34. data/test/fixtures/responses/yahoo/unknown_address.xml +6 -0
  35. data/test/mocks/uri.rb +51 -0
  36. data/test/test_helper.rb +31 -0
  37. data/test/unit/graticule/distance_test.rb +30 -0
  38. data/test/unit/graticule/geocoder_test.rb +31 -0
  39. data/test/unit/graticule/geocoders/geocoder_us_test.rb +42 -0
  40. data/test/unit/graticule/geocoders/geocoders.rb +56 -0
  41. data/test/unit/graticule/geocoders/google_test.rb +22 -0
  42. data/test/unit/graticule/geocoders/meta_carta_test.rb +70 -0
  43. data/test/unit/graticule/geocoders/yahoo_test.rb +49 -0
  44. data/test/unit/graticule/location_test.rb +38 -0
  45. metadata +102 -0
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <kml xmlns="http://earth.google.com/kml/2.0">
3
+ <Response>
4
+ <name>1600</name>
5
+ <Status>
6
+ <code>602</code>
7
+ <request>geocode</request>
8
+ </Status>
9
+ </Response>
10
+ </kml>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE Locations SYSTEM "Locations.dtd">
3
+ <Locations xmlns:gml="http://www.opengis.net/gml" CreatedBy="MetaCarta GeoParser v3.5.0-labs-alpha" CreatedOn="Sat Jun 17 02:05:42 2006" ConvertedFromBinaryFormat="False" InputByteLength="0">
4
+ <ViewBox>
5
+ <gml:Box srsName="epsg:4326">
6
+ <gml:coordinates>-90.000000,-180.000000 90.000000,180.000000</gml:coordinates>
7
+ </gml:Box>
8
+ </ViewBox>
9
+ </Locations>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE Locations SYSTEM "Locations.dtd">
3
+ <Locations xmlns:gml="http://www.opengis.net/gml" CreatedBy="MetaCarta GeoParser v3.5.0-labs-alpha" CreatedOn="Sat Jun 17 02:14:05 2006" ConvertedFromBinaryFormat="False" InputByteLength="1">
4
+ <ViewBox>
5
+ <gml:Box srsName="epsg:4326">
6
+ <gml:coordinates>43.800000,-126.133333 51.406390,-118.530830</gml:coordinates>
7
+ </gml:Box>
8
+ </ViewBox>
9
+ <Location Name="Seattle" Type="PPL" Population="563374" Hierarchy="United States/Washington/King/Seattle">
10
+ <ViewBox>
11
+ <gml:Box srsName="epsg:4326">
12
+ <gml:coordinates>43.806390,-126.130830 51.406390,-118.530830</gml:coordinates>
13
+ </gml:Box>
14
+ </ViewBox>
15
+ <Centroid>
16
+ <gml:Point>
17
+ <gml:coordinates>-122.330830000000006,47.606389999999998</gml:coordinates>
18
+ </gml:Point>
19
+ </Centroid>
20
+ </Location>
21
+ <Location Name="Seattle" Type="PRT" Population="-1" Hierarchy="United States/Seattle">
22
+ <ViewBox>
23
+ <gml:Box srsName="epsg:4326">
24
+ <gml:coordinates>43.800000,-126.133333 51.400000,-118.533333</gml:coordinates>
25
+ </gml:Box>
26
+ </ViewBox>
27
+ <Centroid>
28
+ <gml:Point>
29
+ <gml:coordinates>-122.333332999999996,47.6</gml:coordinates>
30
+ </gml:Point>
31
+ </Centroid>
32
+ </Location>
33
+ </Locations>
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE Locations SYSTEM "Locations.dtd">
3
+ <Locations xmlns:gml="http://www.opengis.net/gml" CreatedBy="MetaCarta GeoParser v3.5.0-labs-alpha" CreatedOn="Thu Jun 15 23:56:50 2006" ConvertedFromBinaryFormat="False" InputByteLength="0">
4
+ <ViewBox>
5
+ <gml:Box srsName="epsg:4326">
6
+ <gml:coordinates>26.238611,37.293889 40.438611,51.493889</gml:coordinates>
7
+ </gml:Box>
8
+ </ViewBox>
9
+ <Location Name="Baghdad" Type="PPLC" Population="5672516" Hierarchy="Iraq/Baghdad/Baghdad">
10
+ <ViewBox>
11
+ <gml:Box srsName="epsg:4326">
12
+ <gml:coordinates>26.238611,37.293889 40.438611,51.493889</gml:coordinates>
13
+ </gml:Box>
14
+ </ViewBox>
15
+ <RemainingQuery/>
16
+ <Confidence>0.195185</Confidence>
17
+ <Centroid>
18
+ <gml:Point>
19
+ <gml:coordinates>44.393889,33.338611</gml:coordinates>
20
+ </gml:Point>
21
+ </Centroid>
22
+ </Location>
23
+ </Locations>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0"?>
2
+ <ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="address"><Latitude>37.416384</Latitude><Longitude>-122.024853</Longitude><Address>701 FIRST AVE</Address><City>SUNNYVALE</City><State>CA</State><Zip>94089-1019</Zip><Country>US</Country></Result></ResultSet>
3
+ <!-- ws01.search.re2.yahoo.com compressed/chunked Sun Oct 15 18:23:09 PDT 2006 -->
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Error xmlns="urn:yahoo:api">
3
+ The following errors were detected:
4
+ <Message>unable to parse location</Message>
5
+ </Error>
6
+ <!-- ws02.search.scd.yahoo.com uncompressed/chunked Thu Jun 8 15:53:20 PDT 2006 -->
@@ -0,0 +1,51 @@
1
+ require 'uri/http'
2
+ require 'open-uri'
3
+
4
+ ##
5
+ # This stub overrides OpenURI's open method to allow programs that use OpenURI
6
+ # to be easily tested.
7
+ #
8
+ # == Usage
9
+ #
10
+ # require 'rc_rest/uri_stub'
11
+ #
12
+ # class TestMyClass < Test::Unit::TestCase
13
+ #
14
+ # def setup
15
+ # URI::HTTP.responses = []
16
+ # URI::HTTP.uris = []
17
+ #
18
+ # @obj = MyClass.new
19
+ # end
20
+ #
21
+ # def test_my_method
22
+ # URI::HTTP.responses << 'some text open would ordinarily return'
23
+ #
24
+ # result = @obj.my_method
25
+ #
26
+ # assert_equal :something_meaninfgul, result
27
+ #
28
+ # assert_equal true, URI::HTTP.responses.empty?
29
+ # assert_equal 1, URI::HTTP.uris.length
30
+ # assert_equal 'http://example.com/path', URI::HTTP.uris.first
31
+ # end
32
+ #
33
+ # end
34
+
35
+ class URI::HTTP # :nodoc:
36
+
37
+ class << self
38
+ attr_accessor :responses, :uris
39
+ end
40
+
41
+ alias original_open open
42
+
43
+ def open
44
+ self.class.uris << self.to_s
45
+ io = StringIO.new(self.class.responses.shift)
46
+ OpenURI::Meta.init(io)
47
+ yield io
48
+ end
49
+
50
+ end
51
+
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+ $:.unshift(File.dirname(__FILE__) + '/mocks')
4
+ $:.unshift(File.dirname(__FILE__)+ '/extra')
5
+
6
+ require 'rubygems'
7
+ require 'yaml'
8
+ require 'test/unit'
9
+ require 'breakpoint'
10
+ require 'graticule'
11
+
12
+ module Test
13
+ module Unit
14
+ module Assertions
15
+
16
+ private
17
+ def response(geocoder, response)
18
+ clean_backtrace do
19
+ File.read(File.dirname(__FILE__) + "/fixtures/responses/#{geocoder}/#{response}.xml")
20
+ end
21
+ end
22
+
23
+ def clean_backtrace(&block)
24
+ yield
25
+ rescue AssertionFailedError => e
26
+ path = File.expand_path(__FILE__)
27
+ raise AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ module Graticule
4
+ module Distance
5
+ class DistanceFormulaTest < Test::Unit::TestCase
6
+ EARTH_RADIUS_IN_MILES = 3963.1676
7
+ EARTH_RADIUS_IN_KILOMETERS = 6378.135
8
+
9
+ FORMULAS = [Haversine, Spherical, Vincenty]
10
+
11
+ def test_earth_radius
12
+ assert_equal EARTH_RADIUS_IN_MILES, EARTH_RADIUS[:miles]
13
+ assert_equal EARTH_RADIUS_IN_KILOMETERS, EARTH_RADIUS[:kilometers]
14
+ end
15
+
16
+ def test_distance
17
+ washington_dc = Location.new(:latitude => 38.898748, :longitude => -77.037684)
18
+ chicago = Location.new(:latitude => 41.85, :longitude => -87.65)
19
+
20
+ FORMULAS.each do |formula|
21
+ assert_in_delta formula.distance(washington_dc, chicago), formula.distance(chicago, washington_dc), 0.1
22
+ assert_in_delta 594.820, formula.distance(washington_dc, chicago), 1.0
23
+ assert_in_delta 594.820, formula.distance(washington_dc, chicago, :miles), 1.0
24
+ assert_in_delta 957.275, formula.distance(washington_dc, chicago, :kilometers), 1.0
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ module Graticule
4
+ class GeocoderTest < Test::Unit::TestCase
5
+
6
+ def test_cannot_instantiate
7
+ assert_raises(NotImplementedError) { Geocoder.new }
8
+ end
9
+
10
+ def test_bogus_service
11
+ assert_equal BogusGeocoder, Graticule.service(:bogus)
12
+ end
13
+
14
+ def test_yahoo_service
15
+ assert_equal YahooGeocoder, Graticule.service(:yahoo)
16
+ end
17
+
18
+ def test_google_service
19
+ assert_equal GoogleGeocoder, Graticule.service(:google)
20
+ end
21
+
22
+ def test_geocoder_us_service
23
+ assert_equal GeocoderUsGeocoder, Graticule.service(:geocoder_us)
24
+ end
25
+
26
+ def test_meta_carta_service
27
+ assert_equal MetaCartaGeocoder, Graticule.service(:meta_carta)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+ require File.dirname(__FILE__) + '/geocoders'
3
+
4
+ module Graticule
5
+ class GeocoderUsTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ URI::HTTP.responses = []
9
+ URI::HTTP.uris = []
10
+
11
+ @geocoder = GeocoderUsGeocoder.new
12
+ @location = Location.new(
13
+ :street => "1600 Pennsylvania Ave NW, Washington DC 20502",
14
+ :longitude => -77.037684,
15
+ :latitude => 38.898748
16
+ )
17
+ end
18
+
19
+ def test_success
20
+ prepare_response(:success)
21
+ assert_equal @location, @geocoder.locate('1600 Pennsylvania Ave, Washington DC')
22
+ end
23
+
24
+ def test_url
25
+ prepare_response(:success)
26
+ @geocoder.locate('1600 Pennsylvania Ave, Washington DC')
27
+ assert_equal 'http://rpc.geocoder.us/service/rest/geocode?address=1600%20Pennsylvania%20Ave,%20Washington%20DC',
28
+ URI::HTTP.uris.first
29
+ end
30
+
31
+ def test_locate_bad_address
32
+ prepare_response(:unknown)
33
+ assert_raises(AddressError) { @geocoder.locate('yuck') }
34
+ end
35
+
36
+ protected
37
+ def prepare_response(id)
38
+ URI::HTTP.responses << response('geocoder_us', id)
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+
4
+ module Graticule
5
+
6
+ # Generic tests for all geocoders (theoretically)
7
+ module GeocodersTestCase
8
+
9
+ def test_success
10
+ return unless prepare_response(:success)
11
+
12
+ location = Location.new(
13
+ :street => "1600 Amphitheatre Pkwy",
14
+ :city => "Mountain View",
15
+ :state => "CA",
16
+ :zip => "94043",
17
+ :country => "US",
18
+ :longitude => -122.083739,
19
+ :latitude => 37.423021,
20
+ :precision => :address
21
+ )
22
+ assert_equal location, @geocoder.locate('1600 Amphitheatre Parkway, Mountain View, CA')
23
+ end
24
+
25
+ def test_bad_key
26
+ return unless prepare_response(:badkey)
27
+ assert_raises(CredentialsError) { @geocoder.locate('x') }
28
+ end
29
+
30
+ def test_locate_missing_address
31
+ return unless prepare_response(:missing_address)
32
+ assert_raises(AddressError) { @geocoder.locate 'x' }
33
+ end
34
+
35
+ def test_locate_server_error
36
+ return unless prepare_response(:server_error)
37
+ assert_raises(Error) { @geocoder.locate 'x' }
38
+ end
39
+
40
+ def test_locate_too_many_queries
41
+ return unless prepare_response(:limit)
42
+ assert_raises(CredentialsError) { @geocoder.locate 'x' }
43
+ end
44
+
45
+ def test_locate_unavailable_address
46
+ return unless prepare_response(:unavailable)
47
+ assert_raises(AddressError) { @geocoder.locate 'x' }
48
+ end
49
+
50
+ def test_locate_unknown_address
51
+ return unless prepare_response(:unknown_address)
52
+ assert_raises(AddressError) { @geocoder.locate 'x' }
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+ require File.dirname(__FILE__) + '/geocoders'
3
+
4
+ module Graticule
5
+ class GoogleGeocoderTest < Test::Unit::TestCase
6
+ # run tests from GeocodersTest
7
+ include GeocodersTestCase
8
+
9
+ def setup
10
+ URI::HTTP.responses = []
11
+ URI::HTTP.uris = []
12
+ @geocoder = GoogleGeocoder.new(:key => 'APP_ID')
13
+ end
14
+
15
+ protected
16
+
17
+ def prepare_response(id = :success)
18
+ URI::HTTP.responses << response('google', id)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+ require File.dirname(__FILE__) + '/geocoders'
3
+
4
+ module Graticule
5
+ class MetaCartaGeocoderTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ URI::HTTP.responses = []
9
+ URI::HTTP.uris = []
10
+
11
+ @geocoder = MetaCartaGeocoder.new
12
+ end
13
+
14
+ def test_locate
15
+ prepare_response(:success)
16
+
17
+ expected = MetaCartaGeocoder::Location.new 'Baghdad', 'PPLC', 5672516,
18
+ 'Iraq/Baghdad/Baghdad',
19
+ 44.393889, 33.338611, 0.195185,
20
+ [[26.238611, 37.293889],
21
+ [40.438611, 51.493889]]
22
+
23
+ location = @geocoder.locate('baghdad')
24
+ assert_equal expected, location
25
+ assert_equal [44.393889, 33.338611], location.coordinates
26
+
27
+ assert_equal true, URI::HTTP.responses.empty?
28
+ assert_equal 1, URI::HTTP.uris.length
29
+ assert_equal 'http://labs.metacarta.com/GeoParser/?output=locations&q=baghdad',
30
+ URI::HTTP.uris.first
31
+ end
32
+
33
+ def test_locate_bad_address
34
+ prepare_response(:bad_address)
35
+ assert_raises(AddressError) { @geocoder.locate('aoeueou') }
36
+ end
37
+
38
+ def test_locations
39
+ prepare_response(:multiple)
40
+
41
+ expected = [
42
+ MetaCartaGeocoder::Location.new('Seattle', 'PPL', 563374,
43
+ 'United States/Washington/King/Seattle',
44
+ -122.33083, 47.60639, nil,
45
+ [[43.806390, -126.130830],
46
+ [51.406390, -118.530830]]),
47
+ MetaCartaGeocoder::Location.new('Seattle', 'PRT', nil,
48
+ 'United States/Seattle',
49
+ -122.333333, 47.6, nil,
50
+ [[43.8, -126.133333],
51
+ [51.4, -118.533333]]),
52
+ ]
53
+
54
+ locations, viewbox = @geocoder.locations('seattle')
55
+ assert_equal expected, locations
56
+ assert_equal [[43.8, -126.133333], [51.40639, -118.53083]], viewbox
57
+
58
+ assert_equal true, URI::HTTP.responses.empty?
59
+ assert_equal 1, URI::HTTP.uris.length
60
+ assert_equal 'http://labs.metacarta.com/GeoParser/?loc=seattle&output=locations',
61
+ URI::HTTP.uris.first
62
+ end
63
+
64
+ protected
65
+ def prepare_response(id = :success)
66
+ URI::HTTP.responses << response('meta_carta', id)
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+ require File.dirname(__FILE__) + '/geocoders'
3
+
4
+ module Graticule
5
+ class YahooGeocoderTest < Test::Unit::TestCase
6
+ #include GeocodersTestCase
7
+
8
+ def setup
9
+ URI::HTTP.responses = []
10
+ URI::HTTP.uris = []
11
+ @geocoder = YahooGeocoder.new 'APP_ID'
12
+ @location = Location.new(
13
+ :street => "701 First Ave",
14
+ :city => "Sunnyvale",
15
+ :state => "CA",
16
+ :zip => "94089-1019",
17
+ :country => "US",
18
+ :longitude => -122.024853,
19
+ :latitude => 37.416384,
20
+ :precision => :address
21
+ )
22
+ end
23
+
24
+ def test_locate
25
+ prepare_response(:success)
26
+ assert_equal [@location], @geocoder.locate('701 First Street, Sunnyvale, CA')
27
+ end
28
+
29
+ def test_url
30
+ prepare_response(:success)
31
+ @geocoder.locate('701 First Street, Sunnyvale, CA')
32
+ assert_equal 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=APP_ID&location=701%20First%20Street,%20Sunnyvale,%20CA&output=xml',
33
+ URI::HTTP.uris.first
34
+ end
35
+
36
+
37
+ def test_locate_bad_address
38
+ prepare_response(:unknown_address)
39
+ assert_raise(Error) { @geocoder.locate('yucksthoeusthaoeusnhtaosu') }
40
+ end
41
+
42
+ protected
43
+ def prepare_response(id)
44
+ URI::HTTP.responses << response('yahoo', id)
45
+ end
46
+
47
+ end
48
+
49
+ end