graticule 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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